webpack簡介與使用

歡迎小夥伴們爲 前端導航倉庫 點star https://github.com/pfan123/fr...
前端導航平臺訪問javascript

CommonJS 和 AMD 是用於 JavaScript 模塊管理的兩大規範,前者定義的是模塊的同步加載,主要用於 NodeJS ;然後者則是異步加載,經過 RequireJS 等工具適用於前端。隨着 npm 成爲主流的 JavaScript 組件發佈平臺,愈來愈多的前端項目也依賴於 npm 上的項目,或者自身就會發布到 npm 平臺。所以,讓前端項目更方便的使用 npm 上的資源成爲一大需求。css

web 開發中經常使用到的靜態資源主要有 JavaScript、CSS、圖片等文件,webpack 中將靜態資源文件稱之爲模塊。 webpack 是一個 module bundler (模塊打包工具),其能夠兼容多種 js 書寫規範,且能夠處理模塊間的依賴關係,具備更強大的 js 模塊化的功能。Webpack 對它們進行統一的管理以及打包發佈,下面這張圖來講明 Webpack 的做用:html

webpack圖片

Webpack的核心原理

Webpack的兩個最核心的原理分別是:前端

1.一切皆模塊java

正如js文件能夠是一個「模塊(module)」同樣,其餘的(如css、image或html)文件也可視做模 塊。所以,你能夠require('myJSfile.js')亦能夠require('myCSSfile.css')。這意味着咱們能夠將事物(業務)分割成更小的易於管理的片斷,從而達到重複利用等的目的。node

2.按需加載jquery

傳統的模塊打包工具(module bundlers)最終將全部的模塊編譯生成一個龐大的bundle.js文件。可是在真實的app裏邊,「bundle.js」文件可能有10M到15M之大可能會致使應用一直處於加載中狀態。所以Webpack使用許多特性來分割代碼而後生成多個「bundle」文件,並且異步加載部分代碼以實現按需加載。webpack

webpack 官網文檔

官網地址:https://webpack.js.org/git

中文官網:https://doc.webpack-china.org/github

webpack 的優點

對 CommonJS 、 AMD 、ES6 的語法作了兼容
對 js、css、圖片等資源文件都支持打包
串聯式模塊加載器以及插件機制,讓其具備更好的靈活性和擴展性,例如提供對 CoffeeScript、ES6的支持
有獨立的配置文件 webpack.config.js
能夠將代碼切割成不一樣的 chunk,實現按需加載,下降了初始化時間
支持 SourceUrls 和 SourceMaps,易於調試
具備強大的 Plugin 接口,大可能是內部插件,使用起來比較靈活
webpack 使用異步 IO 並具備多級緩存。這使得 webpack 很快且在增量編譯上更加快

webpack 安裝和配置

安裝
npm install -g webpack  //全局安裝 npm install --save-dev webpack //局部安裝
執行
webpack —config webpack.config.js
配置

每一個項目下都必須配置有一個 webpack.config.js一般放在項目的根目錄中,它自己也是一個標準的Commonjs規範的模塊。在導出的配置對象中有幾個關鍵的參數:

entry

entry 參數定義了打包後的入口文件,能夠是個字符串或數組或者是對象;若是是數組,數組中的全部文件會打包生成一個filename文件;若是是對象,能夠將不一樣的文件構建成不一樣的文件:

entry: { index: "./page1/index.js", //支持數組形式,將加載數組中的全部模塊,但以最後一個模塊做爲輸出 login: ["./entry1/login.js", "./entry2/register.js"] }
output

output參數是個對象,定義了輸出文件的位置及名字:

output: {  path: path.resolve(__dirname, "build"), //打包輸出路徑,建議絕對路徑 // 配置文件在html中引用的根路徑,改變靜態資源引入的相對路徑  publicPath: "/assets/", //publicPath: "http://cdn.com/assets/",//可加上完整的url,效果與上面一致  filename: "js/bundle.js", // 單頁應用只有一個入口文件時使用,引用入口模塊  filename: "js/[name].js", // 傳統多頁應用有多個入口文件時使用,[name] 代入entry配置中的任意一項模塊的名稱,如:index  filename: "js/[hash]/[chunkhash].js", // 爲生產環境實現前端靜態資源增量更新時使用,[hash]是根據每次編譯後項目整體文件的hash值, [chunkhash]是根據每一個模塊內容計算出的hash值 }
module

在webpack中JavaScript,CSS,LESS,TypeScript,JSX,CoffeeScript,圖片等靜態文件都是模塊,不一樣模塊的加載是經過模塊加載器(webpack-loader)來統一管理的:

module: { rules: [ { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'file-loader', query: { limit: 8192, name: './images/[name].[ext]?[hash]' }, }, // 使用多個插件,使用use,sass文件使用style-loader, css-loader, less-loader來處理 { test: /\.(sass|scss)$/, use: [ 'style-loader', 'css-loader', 'sass-loader', extractTextPlugin.extract(['style','css', 'less']) ], } ] }

注意: webpack 2.x 以後 module.loaders改爲了module.rules

resolve

webpack在構建包的時候會按目錄的進行文件的查找,resolve屬性中的extensions數組中用於配置程序能夠自行補全哪些文件後綴:

resolve: { modules: [path.resolve(__dirname, "node_modules")] extensions: ['', '.js', '.json', '.scss'], //模塊別名定義,方便後續直接引用別名,無須多寫長長的地址 alias: { AppStore : 'js/stores/AppStores.js',//後續直接 require('AppStore') 便可 ActionType : 'js/actions/ActionType.js', AppAction : 'js/actions/AppAction.js' } }
plugin

webpack提供了[豐富的組件]用來知足不一樣的需求,固然咱們也能夠自行實現一個組件來知足本身的需求:

plugins: [ //your plugins list ]

經常使用插件:

  • HotModuleReplacementPlugin --開啓全局的模塊熱替換(HMR)

  • NamedModulesPlugin --當模塊熱替換(HMR)時在瀏覽器控制檯輸出對用戶更友好的模塊名字信息

  • CommonsChunkPlugin --提取chunk公共部分

  • ExtractTextPlugin --獨立生成css文件,之外鏈的形式加載

  • UglifyJsPlugin --壓縮js

  • HtmlWebpackPlugin --使用模版生成html

externals

防止將某些 import 的包(package)打包到 bundle 中,而是在運行時(runtime)再去從外部獲取這些擴展依賴(external dependencies)。

例如,從 CDN 引入 jQuery,而不是把它打包:

<script src="https://code.jquery.com/jquery-3.1.0.js" integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk=" crossorigin="anonymous"></script>
externals: { "jquery": "jQuery" }

這樣就剝離了那些不須要改動的依賴模塊,換句話,下面展現的代碼還能夠正常運行:

import $ from 'jquery'; $('.my-element').animate(...); 

webpack-dev-server

webpack-dev-server是一個小型的node.js Express服務器,它使用webpack-dev-middleware中間件來爲經過webpack打包生成的資源文件提供Web服務。它還有一個經過Socket.IO鏈接着webpack-dev-server服務器的小型運行時程序。webpack-dev-server發送關於編譯狀態的消息到客戶端,客戶端根據消息做出響應。

webpack-dev-server有兩種模式支持自動刷新:

  • iframe模式

  • inline模式

iframe模式

頁面是嵌套在一個iframe下的,在代碼發生改動的時候,這個iframe會從新加載。

使用iframe模式無需額外的配置,只需在瀏覽器輸入 http://localhost:8080/webpack-dev-server/index.html ,顯然webpack-dev-server默認的模式就是iframe

inline模式

的webpack-dev-server客戶端會做爲入口文件打包,會在後端代碼改變的時候刷新頁面。配置方式有兩種:CLI配置和經過Node.js Api手動配置

CLI 方式

此方式比較簡單,只需在webpack.dev.server啓動的命令中加入--inline便可

  • 修改package.json中scripts配置,添加--inline:

"scripts":{ "start":"webpack-dev-server --inline --config webpack.config.dev.js" } 
  • 從新運行npm start,瀏覽器訪問 http://localhost:8080 便可,修改代碼後保存,瀏覽器自動刷新

Node.js Api方式

  • 第一種方案:將webpack/hot/dev-server配置到全部webpack入口文件中

var config = require("./webpack.config.js"); config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080/"); var compiler = webpack(config); var server = new WebpackDevServer(compiler, {...}); server.listen(8080);
  • 第二種方案:將webpack-dev-server客戶端腳本插入到html中便可:

<script src="http://localhost:8080/webpack-dev-server.js"></script>

Hot Module Replacement

使用webpack-dev-server的自動刷新功能時,瀏覽器會整頁刷新。而熱替換的區別就在於,前端代碼變更時,無需刷新整個頁面,只把變化的部分替換掉。配置的關鍵在於將 webpack/hot/dev-server` 文件加入到webpack全部入口文件中。

ps: 使用前要注入 HMR插件

// 開啓全局的模塊熱替換(HMR) new webpack.HotModuleReplacementPlugin(), // 當模塊熱替換(HMR)時在瀏覽器控制檯輸出對用戶更友好的模塊名字信息 new webpack.NamedModulesPlugin()

使用HMR一樣一樣有兩種方式:CLI和Node.js Api

CLI方式

命令行配置比較簡單,只需在自動刷新的基礎上,加上 --hot 配置便可。
此配置會自動將 webpack/hot/dev-server 添加到webpack全部入口點中。

"scripts":{ "start":"webpack-dev-server --inline --hot --config webpack.config.dev.js" }

Node.js Api方式

var config = require("./webpack.config.js"); config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080/", "webpack/hot/dev-server"); var compiler = webpack(config); var server = new webpackDevServer(compiler, {  hot: true ... }); server.listen(8080);

ps:要使HMR功能生效,就是要在應用熱替換的模塊或者根模塊裏面加入容許熱替換的代碼。不然,熱替換不會生效,仍是會重刷整個頁面。下面是摘自webpack在github上docs的原話:

ps: 注意 webpack-dev-server 輸出日誌

//webpack-dev-server.js輸出信息,能夠發現 //contentBase存在,都會打印日誌 Content not from webpack is served from //webpack output is served from信息取自 output.publicPath 路徑 function reportReadiness(uri, options) { const useColor = argv.color; let startSentence = `Project is running at ${colorInfo(useColor, uri)}` if(options.socket) { startSentence = `Listening to socket at ${colorInfo(useColor, options.socket)}`; } console.log((argv["progress"] ? "\n" : "") + startSentence); console.log(`webpack output is served from ${colorInfo(useColor, options.publicPath)}`); const contentBase = Array.isArray(options.contentBase) ? options.contentBase.join(", ") : options.contentBase; if(contentBase) console.log(`Content not from webpack is served from ${colorInfo(useColor, contentBase)}`); if(options.historyApiFallback) console.log(`404s will fallback to ${colorInfo(useColor, options.historyApiFallback.index || "/index.html")}`); if(options.open) { open(uri).catch(function() { console.log("Unable to open browser. If you are running in a headless environment, please do not use the open flag."); }); } }

WEBPACK DEV SERVER

Hot Module Replacement

Hot Module Replacement 介紹

Hot Module Replacement

如何寫好.babelrc?Babel的presets和plugins配置解析

webpack2異步加載套路

基於webpack搭建前端工程解決方案探索

【翻譯】Webpack——使人困惑的地方

相關文章
相關標籤/搜索