您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關webpack中多頁面/入口支持與公共組件單獨打包的示例分析,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
基礎結構和準備工作
以下示例基于上一篇進行改進,上一篇項目源碼
目錄結構說明
. ├── package.json # 項目配置 ├── src # 源碼目錄 │ ├── pageA.html # 入口文件a │ ├── pageB.html # 入口文件b │ ├── css/ # css資源 │ ├── img/ # 圖片資源 │ ├── js # js&jsx資源 │ │ ├── pageA.js # a頁面入口 │ │ ├── pageB.js # b頁面入口 │ │ ├── lib/ # 沒有存放在npm的第三方庫或者下載存放到本地的基礎庫,如jQuery、Zepto、avalon │ ├── pathmap.json # 手動配置某些模塊的路徑,可以加快webpack的編譯速度 ├── webpack.config.js # webpack配置入口
一:自動構建入口
官方多入口示例
webpack默認支持多入口,官方也有多入口的示例。配件文件webpack.config.js如下
//已簡化 var path = require("path"); module.exports = { entry: { pageA: "./pageA", pageB: "./pageB" }, output: { path: path.join(__dirname, "js"), filename: "[name].bundle.js", chunkFilename: "[id].chunk.js" } }
每新增一個頁面就需要在webpack.config.js的entry 中增加一個 pageC:"./pageC",頁面少還好,頁面一多,就有點麻煩了,而且配置文件,盡可能不改動。那么如何支持不修改配置呢?
自動構建入口函數
entry實際上是一個map對象,結構如下{filename:filepath},那么我們可以根據文件名匹配,很容易構造自動掃描器:
npm 中有一個用于文件名匹配的 glob模塊,通過glob很容易遍歷出src/js目錄下的所有js文件:
安裝glob模塊
$ npm install glob --save-dev
修改webpack.config.js 配置,新增entries函數,修改entry:entries(),修改output的filename為"[name].js"
//引入glob var glob = require('glob') //entries函數 var entries= function () { var jsDir = path.resolve(srcDir, 'js') var entryFiles = glob.sync(jsDir + '/*.{js,jsx}') var map = {}; for (var i = 0; i < entryFiles.length; i++) { var filePath = entryFiles[i]; var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.')); map[filename] = filePath; } return map; } //修改入口,已經修改outp的filename module.exports = { //entry: "./src/js/index.js", entry: entries(), output: { path: path.join(__dirname, "dist"), filename: "[name].js" }, ...... //以下省略,可以見下文詳細配置
測試
1.在src/js目錄中新增pageA.js
//js只有兩行代碼,在body中加一句話 var $ = require("jquery") $("<div>這是jquery生成的多頁面示例</div>").appendTo("body")
2.新增pageA.html,也順便修改原來的index.html 對于js文件名的更改
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <script src="../dist/index.js"></script> </body> </html>
3.執行webpack,啟動dev-server
$ webpack $ webpack-dev-server
OK,成功打包生成pageA.js,成功運行
二:公共庫單獨打包
先來分析下,上個步驟打包的日志:
index.js 依賴了avalon 和 jquery,然后打包后的index.js 有480kb
pageA.js 只用了jquery,然后打包后的js 有294kb
那么如果引用的lib庫多一點,又被很多頁面引用,那么lib庫就會被重復打包到page.js中去,模塊越多重復加載的情況越嚴重。
如果把公共代碼提取出來作為單獨的js,那么就到處可以復用,瀏覽器也就可以進行緩存,這時候就需要用到webpack內置插件WebPack.optimize.CommonsChunkPlugin
CommonsChunkPlugin 介紹
使用
new webpack.optimize.CommonsChunkPlugin(options)
Options
翻譯得比較簡單,詳見官方說明:
options.name or options.names(string|string[]): 公共模塊的名稱
options.filename (string): 公開模塊的文件名(生成的文件名)
options.minChunks (number|Infinity|function(module,count) - boolean): 為number表示需要被多少個entries依賴才會被打包到公共代碼庫;為Infinity 僅僅創建公共組件塊,不會把任何modules打包進去。并且提供function,以便于自定義邏輯。
options.chunks(string[]):只對該chunks中的代碼進行提取。
options.children(boolean):如果為true,那么公共組件的所有子依賴都將被選擇進來
options.async(boolean|string):如果為true,將創建一個 option.name的子chunks(options.chunks的同級chunks) 異步common chunk
options.minSize(number):所有公共module的size 要大于number,才會創建common chunk
2個常用的例子,更多例子見官方說明:
1.Commons chunk for entries:針對入口文件提取公共代碼
new CommonsChunkPlugin({ name: "commons", // (the commons chunk name) filename: "commons.js", // (the filename of the commons chunk) // minChunks: 3, // (Modules must be shared between 3 entries) // chunks: ["pageA", "pageB"], // (Only use these entries) })
2.Explicit vendor chunk:直接指定第三方依賴庫,打包成公共組件
entry: { vendor: ["jquery", "other-lib"], app: "./entry" } new CommonsChunkPlugin({ name: "vendor", // filename: "vendor.js" // (Give the chunk a different name) minChunks: Infinity, // (with more entries, this ensures that no other module // goes into the vendor chunk) })
CommonsChunkPlugin使用
基于上篇的項目,參考上面的第二個例子,我們將jquery 和 avalon 提取出來打包成vendor.js
完整的webpack.config.js 如下:
```js var webpack = require("webpack"); var path = require("path"); var srcDir = path.resolve(process.cwd(), 'src'); var nodeModPath = path.resolve(__dirname, './node_modules'); var pathMap = require('./src/pathmap.json'); var glob = require('glob') var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin; var entries= function () { var jsDir = path.resolve(srcDir, 'js') var entryFiles = glob.sync(jsDir + '/*.{js,jsx}') var map = {}; for (var i = 0; i < entryFiles.length; i++) { var filePath = entryFiles[i]; var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.')); map[filename] = filePath; } return map; } module.exports = { //entry: "./src/js/index.js", //entry: entries(), entry: Object.assign(entries(), { // 用到什么公共lib(例如jquery.js),就把它加進vendor去,目的是將公用庫單獨提取打包 'vendor': ['jquery', 'avalon'] }), output: { path: path.join(__dirname, "dist"), filename: "[name].js" }, module: { loaders: [ {test: /\.css$/, loader: 'style-loader!css-loader'} ] }, resolve: { extensions: ['.js', "", ".css"], root: [srcDir,nodeModPath], alias: pathMap, publicPath: '/' }, plugins: [ new CommonsChunkPlugin({ name: 'vendor', minChunks: Infinity }) ] } ```
測試、驗證
1.修改入口(Object.assign 是html5.js里面的....)
//entry: entries(), entry: Object.assign(entries(), { // 用到什么公共lib(例如jquery.js),就把它加進vendor去,目的是將公用庫單獨提取打包 'vendor': ['jquery', 'avalon'] }),
2.加入插件CommonsChunkPlugin
var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin; config 中增加 plugins plugins: [ new CommonsChunkPlugin({ name: 'vendor', minChunks: Infinity }) ]
3.修改index.html 和 pageA.html,增加對verdor.js的引用
<script src="../dist/vendor.js"></script> <script src="../dist/index.js"></script> //<script src="../dist/pageA.js"></script>
4.執行webpack
$ webpack
結果分析
可以看到index.js 就只有457 bytes了,pageA.js 227bytes。vendor.js 是集成了jquery+avalon,所以有488kb。
這樣vendor.js 就可以重復利用了,也方便瀏覽器進行緩存。
調試過程中發現
Uncaught ReferenceError: webpackJsonp is not defined
這個是因為當時把vendor.js引入 放到了page.js 后面,導致page.js執行異常,所以,請一定把vendor.js 放在前面。
生成后的index.js就很輕便了,第三方庫都被打包到vendor中了,代碼如下:
webpackJsonp([0],[ /* 0 */ /***/ function(module, exports, __webpack_require__) { /** * Created by sloong on 2016/6/1. */ //avalon 測試 var avalon = __webpack_require__(1); avalon.define({ $id: "avalonCtrl", name: "Hello Avalon!" }); /* //zepto 測試 require("zepto") $("<div>這是zepto生成的</div>").appendTo("body")*/ //jquery 測試 var $ = __webpack_require__(2) $("<div>這是jquery生成的</div>").appendTo("body") /***/ } ]);
頁面測試均正常
關于“webpack中多頁面/入口支持與公共組件單獨打包的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。