- 首先在桌面建一个 webpacktest
- 在命令行中进入 webpacktest 文件夹 ``` cd Desktop cd webpacktest
3. 项目初始化,前提是全局已安装 webpack 这个模块
npm init
4. 在项目中新建 webpack.cnfig.js 文件
4. 在命令行中,给项目装 webpack 包
cnpm install webpack —save
6. 在项目中新建文件夹<br />
assets 为静态资源, .es .less 方便后面的 loader
> assets -> scripts -> index.es<br />
assets -> styles -> index.less<br />
assets -> html
7. 编辑 index.less
body{ background:black; h1{ color:yellowgreen; } }
8. 编辑 index.es 文件
require(‘../styles/index.less’); const data = 123; console.log(data);
9. 编辑 index.html 文件
<!DOCTYPE html>
<Hello Webpack
10. 编辑 webpack.cnfig.js 文件
//安装一个路径方法的包,这样就不用那么麻烦的写路径了 const path = require(‘path’); // Webpack2 与 1 还是一样的用这个配置 五个模块 module.exports = { //配置资源入口 entry: { //这里的值如果是多个的话写成数组就可以 了 ‘index’: ‘./assets/scripts/index.es’ }, //配置输出到的位置 output: { //后面的值表示:指定编译之后的文件到哪里去 path: path.join(__dirname, ‘./assets/‘), //这个是资源生成之后在每个文件前面加 ./ 这个是本地这样写 如果是上线的话 要换成 公司对应的网址 https://xxx.com/ publicPath: ‘./‘, //这个实际上是将文件名称生成 index.bundle.js 这样的 filename: ‘scripts/[name].bundle.js’ } //配置 loader 用来处理文件 module: { //这个相当于是将 webpack 1 中的 loaders 写到了这个 rules 里 rules: [{ //要处理的文件 后面是正则匹配的 以.es 结尾的文件 test: /.es$/, //这个是指明用哪些 loader 去处理上面选中的文件 use: [{ loader: ‘babel-loader’, //配置 babel-loader options: { //需要先装 babel-loader 包 } }] }] } }
11. 安装 loader -> babel-loader
//-dev 是表示这个包只在生产环境使用,上线就用不着了 cnpm install babel-loader —save-dev
12. 配置解析 .es 文件的 loader
{ //要处理的文件 后面是正则匹配的 以.es 结尾的文件 test: /.es$/, //这个是指明用哪些 loader 去处理上面选中的文件 use: [{ loader: ‘babel-loader’, //配置 babel-loader options: { ‘presets’: [‘es2015’, ‘stage-0’] } }] }
13. 配置解析 .less 文件的 loader
{ test: /.less$/i, use: ExtractTextPlugin.extract({ //fallback 的作用是所有的loader 都引用失败了 最后用我这个后面的loader fallback: ‘style-loader’, //正常情况下用的 loader use: [{ loader: ‘css-loader’ }, { loader: ‘less-loader’ }] }) }
装包
> 参考链接:[https://www.npmjs.com/package/extract-text-webpack-plugin](https://www.npmjs.com/package/extract-text-webpack-plugin)
cnpm install extract-text-webpack-plugin —save-dev
在 webpack.config.js 文件中引入
const ExtractTextPlugin = require(“extract-text-webpack-plugin”);
装包
cnpm install style-loader —save-dev cnpm install css-loader —save-dev cnpm install less-loader —save-dev
14. 此时运行程序 $ webpack,报出如下图所示的错误
> <br />
接续装包
//不加 -dev 因为在真实的生产环境可能会用到 babel-core cnpm install babel-core —save //babel 编译时一定会用到的两个包 cnpm install babel-preset-es2015 —save-dev cnpm install babel-preset-stage-0 —save-dev
15. 此时运行程序 $ webpack, 还是会报错如下图所示的错误
> <br />
需要在 module.exports 中再配一个 plugins 模块
plugins:[ new ExtractTextPlugin(‘styles/[name].css’) ]
16. 在执行程序 $ webpack ,报如下错误
> <br />
继续装报错中未找到的包
cnpm install less —save-dev
17. 再次执行程序 $ webpack ,编译成功了
> 
18. 此时会发现在 styles 文件夹下生成了一个 index.css 文件,scripts 文件夹下生成了一个 index.bundle.js 文件<br />
index.css
body { background: black; } body h1 { color: yellowgreen; }
index.bundle.js
/**/ (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; }; /**/ webpackrequire.d(getter, ‘a’, getter); /**/ return getter; /**/ }; /**/ /**/ // Object.prototype.hasOwnProperty.call /**/ webpackrequire.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /**/ /**/ // webpackpublicpath /**/ webpackrequire.p = “./“; /**/ /**/ // Load entry module and return exports /**/ return webpackrequire(__webpack_require.s = 0); /**/ }) /**/ /**/ ([ / 0 / /*/ (function(module, exports, __webpack_require) {
“use strict”;
webpack_require(1); var data = 123; console.log(data);
// }), / 1 / // (function(module, exports) {
// removed by extract-text-webpack-plugin
// }) /*/ ]);
19. 此时会发现写了一点东西编译出来的就这么的复杂,所以需要化简<br />
在 webpack.config.js 文件中引入 webpack
//头部引用 const webpack = require(‘webpack’);
//plugins -> 配置里新增 //生成一个公用的 如果有两个以上的文件同样的引用一样的js 代码 它就会生成一个 common.js 文件 new webpack.optimize.CommonsChunkPlugin({ name:’common’, filename:’scripts/[name].js’, //引用了两次以上 minChunks:2 })
20. 执行程序 $ webpack<br />
查看 scripts 文件夹多了一个 common.js 文件<br />
common.js
/**/ (function(modules) { // webpackBootstrap /**/ // install a JSONP callback for chunk loading /**/ var parentJsonpFunction = window[“webpackJsonp”]; /**/ window[“webpackJsonp”] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) { /**/ // add “moreModules” to the modules object, /**/ // then flag all “chunkIds” as loaded and fire callback /**/ var moduleId, chunkId, i = 0, resolves = [], result; /**/ for(;i < chunkIds.length; i++) { /**/ chunkId = chunkIds[i]; /**/ if(installedChunks[chunkId]) { /**/ resolves.push(installedChunks[chunkId][0]); /**/ } /**/ installedChunks[chunkId] = 0; /**/ } /**/ for(moduleId in moreModules) { /**/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { /**/ modules[moduleId] = moreModules[moduleId]; /**/ } /**/ } /**/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules); /**/ while(resolves.length) { /**/ resolves.shift()(); /**/ } /**/ if(executeModules) { /**/ for(i=0; i < executeModules.length; i++) { /**/ result = webpack_require(webpack_require.s = executeModules[i]); /**/ } /**/ } /**/ return result; /**/ }; /**/ /**/ // The module cache /**/ var installedModules = {}; /**/ /**/ // objects to store loaded and loading chunks /**/ var installedChunks = { /**/ 1: 0 /**/ }; /**/ /**/ // 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; /**/ } /**/ /**/ // This file contains only the entry chunk. /**/ // The chunk loading function for additional chunks /**/ webpack_require.e = function requireEnsure(chunkId) { /**/ var installedChunkData = installedChunks[chunkId]; /**/ if(installedChunkData === 0) { /**/ return new Promise(function(resolve) { resolve(); }); /**/ } /**/ /**/ // a Promise means “currently loading”. /**/ if(installedChunkData) { /**/ return installedChunkData[2]; /**/ } /**/ /**/ // setup Promise in chunk cache /**/ var promise = new Promise(function(resolve, reject) { /**/ installedChunkData = installedChunks[chunkId] = [resolve, reject]; /**/ }); /**/ installedChunkData[2] = promise; /**/ /**/ // start chunk loading /**/ var head = document.getElementsByTagName(‘head’)[0]; /**/ var script = document.createElement(‘script’); /**/ script.type = ‘text/javascript’; /**/ script.charset = ‘utf-8’; /**/ script.async = true; /**/ script.timeout = 120000; /**/ /**/ if (webpack_require.nc) { /**/ script.setAttribute(“nonce”, webpack_require.nc); /**/ } /**/ script.src = webpack_require.p + “scripts/“ + chunkId + “.bundle.js”; /**/ var timeout = setTimeout(onScriptComplete, 120000); /**/ script.onerror = script.onload = onScriptComplete; /**/ function onScriptComplete() { /**/ // avoid mem leaks in IE. /**/ script.onerror = script.onload = null; /**/ clearTimeout(timeout); /**/ var chunk = installedChunks[chunkId]; /**/ if(chunk !== 0) { /**/ if(chunk) { /**/ chunk1); /**/ } /**/ installedChunks[chunkId] = undefined; /**/ } /**/ }; /**/ head.appendChild(script); /**/ /**/ return promise; /**/ }; /**/ /**/ // 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; }; /**/ webpackrequire.d(getter, ‘a’, getter); /**/ return getter; /**/ }; /**/ /**/ // Object.prototype.hasOwnProperty.call /**/ webpackrequire.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /**/ /**/ // webpackpublicpath /**/ webpack_require.p = “./“; /**/ /**/ // on error function for async loading /**/ __webpack_require.oe = function(err) { console.error(err); throw err; }; /**/ }) /**/ /**/ ([]);
同时会发现 index.bundle.js 文件发生了改变 简化了很多,其实是把公用的 js 放到了 comment.js 文件中
webpackJsonp([0],[ / 0 / /*/ (function(module, exports, webpack_require) {
“use strict”;
webpack_require(1); var data = 123; console.log(data);
// }), / 1 / // (function(module, exports) {
// removed by extract-text-webpack-plugin
/*/ }) ],[0]);
21 . 编辑 html 文件,在浏览器中打开,并查看 js 是否编译成功了<br />
index.html
<!DOCTYPE html>
<Hello Webpack
效果如下图所示
> 
22. 接下来装一个 可以将资源 自动引入 html 的插件
> 参考链接:[https://www.npmjs.com/package/html-webpack-plugin](https://www.npmjs.com/package/html-webpack-plugin)
cnpm install html-webpack-plugin —save-dev
23. 编辑 wepack.config.js 文件
const HtmlWebpackPlugin = require(‘html-webpack-plugin’);
24. 在项目一级目录下新建一个 index.html 文件<br />
index.html
<!DOCTYPE html>
Hello Webpack
将 assets -> index.html 文件中的代码全部删掉<br />
25. 编辑 wepack.config.js 文件
//plugins -> 配置里新增 new HtmlWebpackPlugin({ //生成的新文件的名称 路径的话 以上面配置的 output path: path.join(__dirname, ‘./assets/‘) 为基准 filename:’index.html’, //生成的新 html 文件 用到的 html 文件 template:’./index.html’, inject:true })
26. 执行程序 $ webpack<br />
此时 assets -> index.html 文件中的代码是自动将 html 和 引入 .css .js 的代码合并到一起的<br />
assets -> index.html
<!DOCTYPE html>
Hello Webpack
27. 注意一个问题是,上线时生成资源的路径要改为线上的地址
> <br />
如:[https://xxxx.com/](https://xxxx.com/) 执行程序 $ webapck<br />
html 生成的结果会如下图所示的这样<br />

28. 接下来是 webpack2 优良性的一些东西<br />
首先是会将你 js 文件中没用到的 js 变量自动给你去掉,在 scripts 文件夹中新建一个 data.es 文件<br />
编辑 data.es 文件
//es6 Map 参考链接:http://es6.ruanyifeng.com/#docs/set-map#Map const m = new Map(); m.set(‘data’,’Index init’); //导出一个函数 export const test = function() { console.log(‘test treeShaking’); } //导出一个属性值 export const data = m.get(‘data’);
编辑 index.es 文件
require(‘../styles/index.less’); import {data} from ‘./data.es’; // const data = 123; console.log(data);
执行程序 $ webpack<br />
index.bundle.js 文件会显示如下
webpackJsonp([0],[ / 0 / /*/ (function(module, exports, webpack_require) {
“use strict”;
var data = _webpack_require(1);
webpack_require(2);
// const data = 123; console.log(_data.data);
// }), / 1 / // (function(module, exports, webpack_require) {
“use strict”;
Object.defineProperty(exports, “__esModule”, { value: true }); //es6 Map 参考链接:http://es6.ruanyifeng.com/#docs/set-map#Map var m = new Map(); m.set(‘data’, ‘Index init’); //导出一个函数 var test = exports.test = function test() { console.log(‘test treeShaking’); }; //导出一个属性值 var data = exports.data = m.get(‘data’);
// }), / 2 / // (function(module, exports) {
// removed by extract-text-webpack-plugin
/*/ }) ],[0]);
发现这里并没有把没用到的 test 函数去掉,需要配置一个插件才行是编辑 webpack.config.js 文件
//plugins -> 配置里新增 //这个是 webpack 自带的模块 不需要装 new webpack.optimize.UglifyJsPlugin({ compress:{ warnings:true }, output:{ comments:false }, sourceMap:false })
执行程序 $ webpack
> <br />
上面有两处警告,此时去查看压缩过的 index.bundle.js 文件,会发现 test 函数 它还在,是因为上面的 babel 编译机制把它给留下了需要改变 babel -> es2015 的参数<br />
编辑 webpack.config.js 文件
//module -> rules 配置里新增 //配置 babel-loader options: { ‘presets’: [ [‘es2015’, { ‘modules’: false }], ‘stage-0’ ] }
命令行中显示结果如下
> <br />
再去查看 index.bundle.js 文件会发现 test 函数已经被去掉了
29. 这时你会想自己写的 js 只是想做一个简单点的事,但是编译的时候会把每个函数都编译成闭包 作用域,这样做有些有违常理,随着 webpack3 的更新,出了一个 scope hoisting 的东西
> 参考链接:[https://zhuanlan.zhihu.com/p/27828233](https://zhuanlan.zhihu.com/p/27828233)
//plugins -> 配置里新增 //这个插件是 webpack3 才有的它比之前的 new webpack.optimize.UglifyJsPlugin() 方法更好地将 js 代码简化了 new webpack.optimize.ModuleConcatenationPlugin()
执行程序 $ webpack 此时去查看 index.bundle.js 文件发现比刚才又精简了一些<br />
30. 举两个简单的示例<br />
编辑 index.es 文件<br />
示例1:
if(false == false){ console.log(1); }
执行程序 $ webpack ,在查看 index.bundle.js (.es 编译后的)文件,会发现上面的 if 判断直接就给你去掉了,直接将里面的console 拿了出来<br />
示例2:
if(false != false){ console.log(1); }
执行程序 $ webpack ,在查看 index.bundle.js (.es 编译后的)文件,会发现上面的 if 判断本身是错误的东西 它会自动将整个 if 判断包含里面的代码全都给你去掉<br />
31. 还要完成一个东西 代码分割 code splitting<br />
在 scripts 文件夹中新建一个 async.es 文件<br />
编辑 async.es 文件
const res = function() { console.log(‘async res’); } export default res;
编辑 index.es 文件
//加载 async.es 文件导出的函数 res 并执行该函数 import(‘./async.es’).then(function(res) { res.default(); });
执行程序 $ webpack ,此时会发现在 scripts 文件夹中自动生成了一个 0.bundle.js 文件,这个是webpack 自动将你异步处理的 js 方法直接新建了一个 js 文件放到了里面,这个东西不会自动引入到 html 中,如果引入了就变成同步了,这个东西是在到服务器上的,会通过 load 异步的资源把它请求过去 这个就是所谓的代码分割<br />
32. 还有其他的需要上线的时候掌握的东西,上面的这些掌握基本就可以了,还有如下这样的例子
//与 plugins 模块平级的 //这个里面是将引用的一些公共 模块放到这里,这样就可以全局使用了,避免重复调用 引用的话还是用 cdn 引用静态资源库里的东西 externals:{ jquery:’window.$’ },
```