ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
## 简单的文件打包 ### 1.创建文件目录 ![](https://box.kancloud.cn/1da4277b3dc6fef179d2782dbd8c45e7_207x259.png) dist:目标生成文件夹;src:源文件夹;src下的script和style:js和css源文件夹。 **index.html** ~~~html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>webpackDemo2</title> </head> <body> <script type="text/javascript" src="bundle.js"> </script> </body> </html> ~~~ **main.js** ~~~ function main(){ return{} } ~~~ **webpack.config.js** ~~~javascript var path = require('path'); // webpack2.0 以后,路径需要引用这个模块 module.exports = { entry: './src/script/main.js', output:{ path: path.resolve(__dirname,'./dist/js'), filename: 'bundle.js' } } ~~~ ### 2.执行webpack命令打包 ![](https://box.kancloud.cn/d2d3ab5f2f9ec531f22a09b28ff53806_417x131.png) 如入口与输出一节类似,我们会看到dist下面多了个js文件夹,并且js文件夹里面多了个bundle.js,: ![](https://box.kancloud.cn/f32470d1be9a146d16a794f4e2d32e1c_195x287.png) **bundle.js自动生成第一个chunk为0** ~~~javascript /* 0 */ /***/ (function(module, exports) { function main(){ return{} } /***/ }) /******/ ]); ~~~ ### 3.两个js文件打包成一个js **修改webpack.config.js** ~~~javascript var path = require('path'); //webpack2.0以后,路径需要引用这个模块 module.exports = { entry: ['./src/script/main.js', './src/script/another.js'], //将entry修改成js文件的数组 output:{ path: path.resolve(__dirname,'./dist/js'), filename: 'bundle.js' } } ~~~ ![](https://box.kancloud.cn/607b0bc9667f51d0958f9d9861df5153_617x152.png) **新的bundle.js** ~~~javascript /* 0 */ /***/ (function(module, exports, __webpack_require__) { __webpack_require__(1); module.exports = __webpack_require__(2); /***/ }), /* 1 */ /***/ (function(module, exports) { function main(){ return{} } /***/ }), /* 2 */ /***/ (function(module, exports) { function another(){ alert('another'); } /***/ }) /******/ ]); ~~~ 新生成的3个chunks,其中chunk0是将两个不相干的模块`_webpack_require(1)`与`webpackrequire__(2)`联系起来。 ### 4.两个文件打包完分别输出各自的打包文件 **修改webpack.config.js** ~~~javascript var path = require('path'); //webpack2.0以后,路径需要引用这个模块 module.exports = { entry: { //将entry修改成对象形式 main: './src/script/main.js', another: './src/script/another.js' }, output:{ path: path.resolve(__dirname,'./dist/js'), filename: 'bundle.js' } } ~~~ 这个时候会出现报错: ![](https://box.kancloud.cn/bf6b7638fb87ab95fa7a5a1edc5b7ce6_504x201.png) 因为两个文件分开输出到各自的打包文件,但是我们输出出口都是bundle.js,所以是错误的。 **再修改webpack.config.js** ~~~javascript var path = require('path'); //webpack2.0以后,路径需要引用这个模块 module.exports = { entry: { main: './src/script/main.js', another: './src/script/another.js' }, output:{ path: path.resolve(__dirname,'./dist/js'), filename: '[name]-[chunkhash]-bundle.js' } } ~~~ 可以在filename中使用[占位符(substitutions)](https://doc.webpack-china.org/configuration/output/#output-filename)来确保每个文件具有唯一的名称。 重新打包生成 ![](https://box.kancloud.cn/6d0f04115a7ed8cb3b61cdf3e50d93f9_635x149.png) 在dist/js下生成了两个js文件 ![](https://box.kancloud.cn/ae72fdc4e509bfa05132456b2fcc2932_352x308.png) **main-df5c09aabd3c2b72c8f4-bundle.js** ~~~javascript /* 0 */ /***/ (function(module, exports) { function main(){ return{} } /***/ }) /******/ ]); ~~~ **another-d6deaccdba4ac37ddc27-bundle.js** ~~~javascript /* 0 */, /* 1 */ /***/ (function(module, exports) { function another(){ alert('another'); } /***/ }) /******/ ]); ~~~ ## 使用plugin,这里介绍[插件html-webpack-plugin](https://www.npmjs.com/package/html-webpack-plugin) ### 1.安装插件 ~~~javascript npm install html-webpack-plugin --save-dev ~~~ ### 2.修改webpack.config ~~~ var path = require('path'); //webpack2.0以后,路径需要引用这个模块 var htmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { main: './src/script/main.js', another: './src/script/another.js' }, output:{ path: path.resolve(__dirname,'./dist/js'), filename: '[name]-[chunkhash]-bundle.js' }, plugins:[ new htmlWebpackPlugin() ] } ~~~ ### 3.打包生成 ![](https://box.kancloud.cn/3a00c3ff97a5877ff5f261f89ec36d84_654x223.png) 发现dist/js下除了新生成的js还有一个index.html文件 ~~~html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Webpack App</title> </head> <body> <script type="text/javascript" src="main-df5c09aabd3c2b72c8f4-bundle.js"></script><script type="text/javascript" src="another-d6deaccdba4ac37ddc27-bundle.js"></script></body> </html> ~~~ 发现生成的index.html自动引入打包后的`another-chunkhash-bundle.js`和`mian-chunkhash-bundle.js`,然而这样生成的html是固定的,研究一下这个插件,我们应该可以利用模板生成自定义的html。 ### 4.利用插件按模板生成html **修改模板index.html** ~~~html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>修改后模板中的title</title> </head> <body> <script type="text/javascript" src="bundle.js"> </script> </body> </html> ~~~ **再次打包生成** ![](https://box.kancloud.cn/80815c10163fff2d4d8e079a3e1f8bd0_750x237.png) **新生成的dist/js下的index.html** 发现title与我们的模板中修改的一样 ~~~html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>修改后模板中的title</title> </head> <body> <script type="text/javascript" src="bundle.js"> </script> <script type="text/javascript" src="main-df5c09aabd3c2b72c8f4-bundle.js"></script><script type="text/javascript" src="another-d6deaccdba4ac37ddc27-bundle.js"></script></body> </html> ~~~ ### 5.分开生成的文件 **修改webpack.config** ~~~javascript var path = require('path'); //webpack2.0以后,路径需要引用这个模块 var htmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { main: './src/script/main.js', another: './src/script/another.js' }, output:{ path: path.resolve(__dirname,'./dist'), filename: 'js/[name]-[chunkhash]-bundle.js' //将相对路径分配到filename中 }, plugins:[ new htmlWebpackPlugin({ template: 'index.html' }) ] } ~~~ ![](https://box.kancloud.cn/eaf61ffc63ec21f83142db0127fda568_739x245.png) **新的文件目录** ![](https://box.kancloud.cn/f1fca94cfe28b4e05f61b06a2f0e3050_205x140.png) ### 6.plugin的[其他options参数](https://www.npmjs.com/package/html-webpack-plugin) **修改webpack.config** ~~~javascript var path = require('path'); //webpack2.0以后,路径需要引用这个模块 var htmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { main: './src/script/main.js', another: './src/script/another.js' }, output:{ path: path.resolve(__dirname,'./dist'), filename: 'js/[name]-[chunkhash]-bundle.js' }, plugins:[ new htmlWebpackPlugin({ template: 'index.html', filename: 'index-[hash].html', inject: 'body', //打包生成的js,css和其他东西注入的位置 title: 'This is my plugin title', minify:{ //压缩代码,下面意思是省去空格、移除注释,更多的查看插件官网 collapseWhitespace: true, removeComments: true, } }) ] } ~~~ **dist下新生成的index-f8cd6c5d985e6b29bd44.html** 发现空格和注释都没了 ~~~ <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>修改后模板中的title</title></head><body><script type="text/javascript" src="bundle.js"></script><script type="text/javascript" src="js/main-ce4b1548dce5dea612ac-bundle.js"></script><script type="text/javascript" src="js/another-f16463e116d027221d92-bundle.js"></script></body></html> ~~~ ### 7.plugin模板产生交互 例如我们想让根目录index.html下面的模板调取webpack.config.js里面plugins的title,我们就需要在根目录index.html用EJS **修改模板index.html** ~~~html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title><%= htmlWebpackPlugin.options.title %></option></title> </head> <body> <script type="text/javascript" src="bundle.js"> </script> <!-- 这里是注释 --> </body> </html> ~~~ **dist下新生成的index(注意title)** ~~~html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>This is my plugin title</title> </head> <body> <script type="text/javascript" src="bundle.js"> </script> <script type="text/javascript" src="js/main-ce4b1548dce5dea612ac-bundle.js"></script><script type="text/javascript" src="js/another-f16463e116d027221d92-bundle.js"></script></body> </html> ~~~ ### 8.获取plugin更多的options **修改webpack.config** ~~~javascript var path = require('path'); //webpack2.0以后,路径需要引用这个模块 var htmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { main: './src/script/main.js', another: './src/script/another.js' }, output:{ path: path.resolve(__dirname,'./dist'), filename: 'js/[name]-[chunkhash]-bundle.js' }, plugins:[ new htmlWebpackPlugin({ template: 'index.html', filename: 'index-[hash].html', inject: 'head', //打包生成的js,css和其他东西注入的位置 title: 'This is my plugin title', date: new Date(), minify:{ //压缩代码,下面意思是省去空格、移除注释,更多的查看插件官网 collapseWhitespace: false, removeComments: true, } }) ] } ~~~ **修改模板index.html** ~~~html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <script type="text/javascript" src="bundle.js"></script> <!-- 这里是注释 --> <%= htmlWebpackPlugin.options.date %> <% for (key in htmlWebpackPlugin.files) {%> <%= key%> : <%= JSON.stringify(htmlWebpackPlugin.files[key]) %> <% } %> <% for (key in htmlWebpackPlugin.options) {%> <%= key%> : <%= JSON.stringify(htmlWebpackPlugin.options[key]) %> <% } %> </body> </html> ~~~ **dist下新生成的index.html** ~~~html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>This is my plugin title</title> <script type="text/javascript" src="js/main-ce4b1548dce5dea612ac-bundle.js"></script><script type="text/javascript" src="js/another-f16463e116d027221d92-bundle.js"></script></head> <body> <script type="text/javascript" src="bundle.js"></script> Mon Jul 17 2017 10:46:53 GMT+0800 (中国标准时间) publicPath : "" chunks : {"main":{"size":33,"entry":"js/main-ce4b1548dce5dea612ac-bundle.js","hash":"ce4b1548dce5dea612ac","css":[]},"another":{"size":45,"entry":"js/another-f16463e116d027221d92-bundle.js","hash":"f16463e116d027221d92","css":[]}} js : ["js/main-ce4b1548dce5dea612ac-bundle.js","js/another-f16463e116d027221d92-bundle.js"] css : [] manifest : template : "E:\\learnFront\\webpack\\webpackDemo3\\node_modules\\html-webpack-plugin\\lib\\loader.js!E:\\learnFront\\webpack\\webpackDemo3\\index.html" filename : "index-[hash].html" hash : false inject : "head" compile : true favicon : false minify : {"collapseWhitespace":false,"removeComments":true} cache : true showErrors : true chunks : "all" excludeChunks : [] title : "This is my plugin title" xhtml : false date : "2017-07-17T02:46:53.124Z" </body> </html> ~~~ 关注到`htmlWebpackPlugin.files.chunks.模块名.entry`是打包生成的chunks路径,我们可以直接在模板index引用 **修改webpack.config(修改inject)** ~~~javascript var path = require('path'); //webpack2.0以后,路径需要引用这个模块 var htmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { main: './src/script/main.js', another: './src/script/another.js' }, output:{ path: path.resolve(__dirname,'./dist'), filename: 'js/[name]-[hash]-bundle.js' }, plugins:[ new htmlWebpackPlugin({ template: 'index.html', filename: 'index-[hash].html', inject: false, //打包生成的js,css和其他东西注入的位置 title: 'This is my plugin title', }) ] } ~~~ **修改模板index.html** ~~~html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title><%= htmlWebpackPlugin.options.title %></title> <script type="text/javascript" src="<%= htmlWebpackPlugin.files.chunks.main.entry %>"></script> <script type="text/javascript" src="<%= htmlWebpackPlugin.files.chunks.another.entry %>"></script> </head> <body> </body> </html> ~~~ **dist下新生成的index.html** 意料之中,直接将生成的js插入了head标签中。 ~~~html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>This is my plugin title</title> <script type="text/javascript" src="js/main-f2dac2790752190964a8-bundle.js"></script> <script type="text/javascript" src="js/another-f2dac2790752190964a8-bundle.js"></script> </head> <body> </body> </html> ~~~ ### 9.将打包后的html引入的js换成线上的地址 **修改webpack.config** ~~~javascript var path = require('path'); //webpack2.0以后,路径需要引用这个模块 var htmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { main: './src/script/main.js', another: './src/script/another.js' }, output:{ path: path.resolve(__dirname,'./dist'), publicPath: 'https://cdn.example.com/', filename: 'js/[name]-[hash]-bundle.js' }, plugins:[ new htmlWebpackPlugin({ template: 'index.html', filename: 'index-[hash].html', inject: false, //打包生成的js,css和其他东西注入的位置 title: 'This is my plugin title', }) ] } ~~~ **dist下新生成的index.html** script中src已经改成线上地址 ~~~html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>This is my plugin title</title> <script type="text/javascript" src="https://cdn.example.com/js/main-60ab79c0b9a1c47b5eed-bundle.js"></script> <script type="text/javascript" src="https://cdn.example.com/js/another-60ab79c0b9a1c47b5eed-bundle.js"></script> </head> <body> </body> </html> ~~~ ## 生成多个页面 ### 1.新建文件目录 在script下创建多个js文件:a、b、c.js ![](https://box.kancloud.cn/f08695bff28e05eb5fe2eea819acb26b_208x267.png) ### 2.修改webpack.config ~~~ var path = require('path'); //webpack2.0以后,路径需要引用这个模块 var htmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { a: './src/script/a.js', b: './src/script/b.js', c: './src/script/c.js', }, output:{ path: path.resolve(__dirname,'./dist'), filename: 'js/[name].js' }, plugins:[ new htmlWebpackPlugin({ template: 'index.html', filename: 'a.html', title: 'This is a', }), new htmlWebpackPlugin({ template: 'index.html', filename: 'b.html', title: 'This is b', }), new htmlWebpackPlugin({ template: 'index.html', filename: 'c.html', title: 'This is c', }), ] } ~~~ **模板index.html** ~~~html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <script src="bundle.js" type="text/javascript" charset="utf-8"></script> </body> </html> ~~~ ### 3.生成的html文件 ~~~html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>This is a</title> </head> <body> <script src="bundle.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript" src="js/c.js"></script><script type="text/javascript" src="js/b.js"></script><script type="text/javascript" src="js/a.js"></script></body> </html> ~~~ 这与我们预期在打包后的a.html只引入a.js,b.html只引入b.js,c.html只引入c.js不一样,这个时候就要去看html-webpack-plugin里面的chunks和excludeChunks: (1) chunks: 指定载入哪些chunk到打包生成的html页面 (2) excludeChunks: 指定排除哪些页面将剩下的chunks载入到打包生成的html页面 ### 4.再次修改webpack.config ~~~javascript var path = require('path'); //webpack2.0以后,路径需要引用这个模块 var htmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { a: './src/script/a.js', b: './src/script/b.js', c: './src/script/c.js', }, output:{ path: path.resolve(__dirname,'./dist'), filename: 'js/[name].js' }, plugins:[ new htmlWebpackPlugin({ template: 'index.html', filename: 'a.html', title: 'This is a', chunks: ['a'] //注意是数组,或者是excludeChunks: ['b', 'c'] }), new htmlWebpackPlugin({ template: 'index.html', filename: 'b.html', title: 'This is b', chunks: ['b'] //注意是数组,或者是excludeChunks: ['a', 'c'] }), new htmlWebpackPlugin({ template: 'index.html', filename: 'c.html', title: 'This is c', chunks: ['c'] //注意是数组,或者是excludeChunks: ['a', 'b'] }), ] } ~~~ **再次生成后的a.html** ~~~html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>This is a</title> </head> <body> <script src="bundle.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript" src="js/a.js"></script></body> </html> ~~~ ## 引入内联js和外链js 我们都知道当html页面引入多个js的时候就需要多次向服务器发送请求,这样会增加带宽消耗和时间消耗,为了解决这个问题,可以将共用的js源码直接写在html,不共用js再外链引入。 之前插件html-webpack-plugin并没有考虑这种内联情况,但是插件的作者给出了在webpack里面打包的[解决方法](https://github.com/jantimon/html-webpack-plugin/blob/master/examples/inline/template.jade) ### 1.新建文件目录 ![](https://box.kancloud.cn/02da85a29054d1ace43e1dc4ce93a237_215x285.png) ### 2.修改webpack.config ~~~javascript var path = require('path'); //webpack2.0以后,路径需要引用这个模块 var htmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { a: './src/script/a.js', b: './src/script/b.js', c: './src/script/c.js', main: './src/script/main.js' }, output: { path: path.resolve(__dirname, './dist'), publicPath: 'https://cdn.example.com/', filename: 'js/[name].js' }, plugins: [ new htmlWebpackPlugin({ template: 'index.html', filename: 'a.html', title: 'This is a', inject: false, excludeChunks: ['b', 'c'] }), new htmlWebpackPlugin({ template: 'index.html', filename: 'b.html', title: 'This is b', inject: false, excludeChunks: ['a', 'c'] }), new htmlWebpackPlugin({ template: 'index.html', filename: 'c.html', title: 'This is c', inject: false, excludeChunks: ['a', 'b'] }) ] } ~~~ ### 3.修改模板index.html ~~~html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> <%= htmlWebpackPlugin.options.title %> </title> <script type="text/javascript"> <%= compilation.assets[htmlWebpackPlugin.files.chunks.main.entry.substr(htmlWebpackPlugin.files.publicPath.length)].source() %> //内联化引入js </script> </head> <body> <% for (var i in htmlWebpackPlugin.files.chunks){%> <% if (i!=='main'){%> <script type="text/javascript" src="<%= htmlWebpackPlugin.files.chunks[i].entry %>"></script> <% } %> <% } %> </body> </html> ~~~ ### 4.成功生成的a.html ~~~html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> This is a </title> <script type="text/javascript"> /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = "https://cdn.example.com/"; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 3); /******/ }) /************************************************************************/ /******/ ({ /***/ 3: /***/ (function(module, exports) { function main() { alert("main"); } /***/ }) /******/ }); //内联化引入js </script> </head> <body> <script type="text/javascript" src="https://cdn.example.com/js/a.js"></script> </body> </html> ~~~ 这样,我们就把main.js内嵌到a、b、c.html中,而以外链的形式引用各个单独的js