[关闭]
@zhouyy 2018-04-03T01:48:08.000000Z 字数 5200 阅读 562

使用 Loader Plugin DevServer

webpack

安装到本项目

  1. # npm i -D 是 npm install --save-dev 的简写,是指安装模块并保存到 package.json 的 devDependencies
  2. # 安装最新稳定版
  3. npm i -D webpack
  4. # 安装指定版本
  5. npm i -D webpack@<version>

安装完后你可以通过这些途径运行安装到本项目的 Webpack:

  1. "scripts": {
  2. "start": "webpack --config webpack.config.js"
  3. }

什么是 npm 脚本?
npm 允许在package.json文件里面,使用scripts字段定义脚本命令。使用自定义脚本,用户可以将一些项目中常用的命令行记录在 package.json 不需要每次都要敲一遍。
npm scripts 不是简简单单地执行 shell 语句而已,在执行之前它会将 node_modules/.bin/ 加入到环境变量 PATH 中,所以在 npm scripts 中可以直接使用那些存在于 node_modules/.bin/ 中的可执行文件。
很多使用 mocha 作为测试框架的项目中都有这么一个 npm script

{
"scripts": {
"build": "node build.js"
}
}

mocha 并没有全局安装,它的命令行工具存在于 node_modules/.bin/ 中在 npm script 执行完成后,会从 PATH 中移除。
在执行 npm run test (后面会看到这可以简写为 npm test) 的时候就等同于:./node_modules/.bin/mocha
**For more

推荐安装到本项目,原因是可防止不同项目依赖不同版本的 Webpack 而导致冲突。

项目目录

  1. |-- index.html
  2. |-- main.js
  3. |-- main.css
  4. |-- show.js
  5. |-- webpack.config.js
  1. // 通过 CommonJS 规范导入 CSS 模块
  2. require('./main.css');
  3. // 通过 CommonJS 规范导入 show 函数
  4. const show = require('./show.js');
  5. // 执行 show 函数
  6. show('Webpack');

配置文件 webpack.config.js

  1. const path = require('path');
  2. module.exports = {
  3. // JavaScript 执行入口文件
  4. entry: './main.js',
  5. output: {
  6. // 把所有依赖的模块合并输出到一个 bundle.js 文件
  7. filename: 'bundle.js',
  8. // 输出文件都放到 dist 目录下
  9. path: path.resolve(__dirname, './dist'),
  10. },
  11. module: {
  12. rules: [
  13. {
  14. // 用正则去匹配要用该 loader 转换的 CSS 文件
  15. test: /\.css$/,
  16. use: ['style-loader', 'css-loader?minimize'],
  17. }
  18. ]
  19. }
  20. };

Loader

因为 Webpack 不原生支持解析 CSS 文件。要支持非 JavaScript 类型的文件,需要使用 Webpack 的 Loader 机制

Loader 可以看作具有文件转换功能的翻译员,配置里的 module.rules 数组配置了一组规则,告诉 Webpack 在遇到哪些文件时使用哪些 Loader 去加载和转换。如上配置告诉 Webpack 在遇到以 .css 结尾的文件时先使用 css-loader 读取 CSS 文件,再交给 style-loader 把 CSS 内容注入到 JavaScript 里。

style-loader 的工作原理大概是把 CSS 内容用 JavaScript 里的字符串存储起来, 在网页执行 JavaScript 时通过 DOM 操作动态地往 HTML head 标签里插入 HTML style 标签。

在配置 Loader 时需要注意的是:

Loader 传入属性的方式除了有 querystring 外,还可以通过 Object 传入:

  1. use: [
  2. 'style-loader',
  3. {
  4. loader:'css-loader',
  5. options:{
  6. minimize:true,
  7. }
  8. }
  9. ]

除了在 webpack.config.js 配置文件中配置 Loader 外,还可以在源码中指定用什么 Loader 去处理文件。 以加载 CSS 文件为例,修改上面例子中的 main.js 如下:

  1. require('style-loader!css-loader?minimize!./main.css');

Plugin

Plugin 是用来扩展 Webpack 功能的,通过在构建流程里注入钩子实现。
上一节中通过 Loader 加载了 CSS 文件,本节将通过 Plugin 把注入到 bundle.js 文件里的 CSS 提取到单独的文件中,配置修改如下:

  1. const path = require('path');
  2. const ExtractTextPlugin = require('extract-text-webpack-plugin');
  3. module.exports = {
  4. // JavaScript 执行入口文件
  5. entry: './main.js',
  6. output: {
  7. // 把所有依赖的模块合并输出到一个 bundle.js 文件
  8. filename: 'bundle.js',
  9. // 把输出文件都放到 dist 目录下
  10. path: path.resolve(__dirname, './dist'),
  11. },
  12. module: {
  13. rules: [
  14. {
  15. // 用正则去匹配要用该 loader 转换的 CSS 文件
  16. test: /\.css$/,
  17. use: ExtractTextPlugin.extract({
  18. // 转换 .css 文件需要使用的 Loader
  19. use: ['css-loader'],
  20. }),
  21. }
  22. ]
  23. },
  24. plugins: [
  25. new ExtractTextPlugin({
  26. // 从 .js 文件中提取出来的 .css 文件的名称
  27. filename: `[name]_[contenthash:8].css`,
  28. }),
  29. ]
  30. };

要让以上代码运行起来,需要先安装新引入的插件:

  1. npm i -D extract-text-webpack-plugin

重新执行构建,你会发现 dist 目录下多出一个 main_1a87a56a.css 文件,bundle.js 里也没有 CSS 代码了,再把该 CSS 文件引入到 index.html 里就完成了。

Webpack 是通过 plugins 属性来配置需要使用的插件列表的。 plugins 属性是一个数组,里面的每一项都是插件的一个实例,在实例化一个组件时可以通过构造函数传入这个组件支持的配置属性。

例如 ExtractTextPlugin 插件的作用是提取出 JavaScript 代码里的 CSS 到一个单独的文件。 对此你可以通过插件的 filename 属性,告诉插件输出的 CSS 文件名称是通过 [name]_[contenthash:8].css 字符串模版生成的,里面的 [name] 代表文件名称, [contenthash:8] 代表根据文件内容算出的8位 hash 值。

DevServer

在实际开发中你可能会需要:

  1. 提供 HTTP 服务而不是使用本地文件预览;
  2. 监听文件的变化并自动刷新网页,做到实时预览;
  3. 支持 Source Map,以方便调试。

Webpack 原生支持上述第2、3点内容,再结合官方提供的开发工具 DevServer 也可以很方便地做到第1点。

DevServer 会启动一个 HTTP 服务器用于服务网页请求,同时会帮助启动 Webpack ,并接收 Webpack 发出的文件更变信号,通过 WebSocket 协议自动刷新网页做到实时预览。

  1. npm i -D webpack-dev-server
  1. webpack-dev-server

DevServer 启动的 HTTP 服务器监听在 http://localhost:8080/ ,DevServer 启动后会一直驻留在后台保持运行,访问这个网址你就能获取项目根目录下的 index.html.用浏览器打开这个地址你会发现页面空白错误原因是 ./dist/bundle.js 加载404了。 同时你会发现并没有文件输出到 dist 目录,原因是 DevServer 会把 Webpack 构建出的文件保存在内存中,在要访问输出的文件时,必须通过 HTTP 服务访问。 由于 DevServer 不会理会 webpack.config.js 里配置的 output.path 属性,所以要获取 bundle.js 的正确 URL 是 http://localhost:8080/bundle.js,对应的 index.html 应该修改为:

  1. <script src="bundle.js"></script>

接着上面的步骤,你可以试试修改 main.js main.css show.js 中的任何一个文件,保存后你会发现浏览器会被自动刷新,运行出修改后的效果。

Webpack 在启动时可以开启监听模式,开启监听模式后 Webpack 会监听本地文件系统的变化,发生变化时重新构建出新的结果。Webpack 默认是关闭监听模式的,你可以在启动 Webpack 时通过 webpack --watch 来开启监听模式

通过 DevServer 启动的 Webpack 会开启监听模式,当发生变化时重新执行完构建后通知 DevServer。 DevServer 会让 Webpack 在构建出的 JavaScript 代码里注入一个代理客户端用于控制网页,网页和 DevServer 之间通过 WebSocket 协议通信, 以方便 DevServer 主动向客户端发送命令。 DevServer 在收到来自 Webpack 的文件变化通知时通过注入的客户端控制网页刷新。

如果尝试修改 index.html 文件并保存,你会发现这并不会触发以上机制,导致这个问题的原因是 Webpack 在启动时会以配置里的 entry 为入口去递归解析出 entry 所依赖的文件,只有 entry 本身和依赖的文件才会被 Webpack 添加到监听列表里。 而 index.html 文件是脱离了 JavaScript 模块化系统的,所以 Webpack 不知道它的存在。

核心概念

Entry:入口,Webpack 执行构建的第一步将从 Entry 开始,可抽象成输入。
Module:模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。
Loader:模块转换器,用于把模块原内容按照需求转换成新内容。
Plugin:扩展插件,在 Webpack 构建流程中的特定时机注入扩展逻辑来改变构建结果或做你想要的事情。
Output:输出结果,在 Webpack 经过一系列处理并得出最终想要的代码后输出结果。

Webpack 启动后会从 Entry 里配置的 Module 开始递归解析 Entry 依赖的所有 Module。 每找到一个 Module, 就会根据配置的 Loader 去找出对应的转换规则,对 Module 进行转换后,再解析出当前 Module 依赖的 Module。 这些模块会以 Entry 为单位进行分组,一个 Entry 和其所有依赖的 Module 被分到一个组也就是一个 Chunk。最后 Webpack 会把所有 Chunk 转换成文件输出。 在整个流程中 Webpack 会在恰当的时机执行 Plugin 里定义的逻辑。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注