第二章:配置(深入浅出 Webpack 笔记)
Entry(配置模块的入口,必填)
context:
Webpack 在寻找相对路径的文件时会以 context 为根目录, context 默认为执行启动 Webpack 时所在的当前工作目录。
// 改变 context 的默认配置
module.exports = {
context: path.resolve (__dirname, 'app')
}
Entry 类型:
string、array、object
Chunk 的名称:
Webpack 会为每个生成的 Chunk 取一个名称,Chunk 的名称和 Entry 的配置有关。
- 如果 Entry 是一个 string 或 array,就只会生成一个 Chunk,这时 Chunk 的名称是 main。
- 如果 Entry 是一个 object,就可能会出现多个 Chunk,这时 Chunk 的名称是 object 键值对中键的名称。
配置动态 Entry:
将 Entry 设置成一个函数动态地返回配置
Output(配置如何输出最终想要的代码)
filename:
配置输出文件的名称,为 string 类型,如果只有一个输出文件,则 可以将它写成静态不变的;
在有多个 Chunk 要输出时,就需要借助模板和变量了 filename: '[name]. js'
chunkFilename:
配置无入口的 Chunk 在输出时的文件名称
path:
配置输出文件存放在本地的目录,必须是 string 类型的绝对路径。
通常通过 Node.js 的 path 模块去获取绝对路径:path: path.resolve(__dirname, 'dist_[hash]')
publicPath:
配置发布到线上资源的 URL 前缀,为 string 类型。 默认值是空字符串 '',即使用相对路径
crossOriginLoading:
用于配置需要异步加载(原理:通过 JSONP 实现, 即动态地向 HTML 中插入一个 <script src="url"></script>
标签去加载异步资源)的代码块标签的 crossorigin
值,可以取以下值:
-
anonymous
(默认) 在加载此脚本资源时不会带上用户的 Cookies; -
use-credentials
在加载此脚本资源时会带上用户的 Cookies。
通常用设置 crossorigin 来获取异步加载的脚本执行时的详细错误信息。
libraryTarget 和 library
当用 Webpack 去构建一个可以被其他模块导入使用的库时需要用到它们。
output.libraryTarget
配置以何种方式导出库。
output.library
配置导出库的名称。
output.libraryTarget
是字符串的枚举类型,支持以下配置。
- var (默认): 编写的库将通过 var 被赋值给通过 library 指定名称的变量
- commonjs:编写的库将通过 CommonJS 规范导出
- commonjs2:编写的库将通过 CommonJS2 规范导出
CommonJS2 和 CommonJS 规范很相似,差别在于 CommonJS 只能用 exports 导出,而 CommonJS2 在 CommonJS 的基础上增加了 module.exports 的导出方式。
在 output.libraryTarget 为 commonjs2 时,配置 output.library 将没有意义。 - this:编写的库将通过 this 被赋值给通过 library 指定的名称
- window:编写的库将通过 window 被赋值给通过 library 指定的名称,即把库挂载到 window 上
- global:编写的库将通过 global 被赋值给通过 library 指定的名称,即把库挂载到 global 上
libraryExport
output.libraryExport
配置要导出的模块中哪些子模块需要被导出,它只有在 output.libraryTarget
被设置成 commonjs 或者 commonjs2 时使用才有意义。
Module(配置如何处理模块)
rules:
配置模块的读取和解析规则,通常用来配置 Loader。其类型是一个数组,数组里每一项都描述了如何去处理部分文件。
1. 条件匹配:通过 test 、 include 、 exclude 三个配置项来命中 Loader 要应用规则的文件,参数可以是一个字符串、正则或数组类型。
2. 应用规则:对选中后的文件通过 use 配置项来应用 Loader,可以只应用一个 Loader 或者按照从后往前的顺序应用一组 Loader,同时还可以分别给 Loader 传入参数。
3. 重置顺序:一组 Loader 的执行顺序默认是从右到左执行,通过 enforce 选项可以让其中一个 Loader 的执行顺序放到最前或者最后。在 Loader 需要传入很多参数时,还可以通过一个 Object 来描述。
noParse:
noParse 配置项可以让 Webpack 忽略对部分没采用模块化的文件的递归解析和处理,这样做的好处是能提高构建性能。
注意被忽略掉的文件里不应该包含 import 、 require 、 define 等模块化语句,不然会导致构建出的代码中包含无法在浏览器环境下执行的模块化语句。
parser:
因为 Webpack 是以模块化的 JavaScript 文件为入口,所以内置了对模块化 JavaScript 的解析功能,支持 AMD、CommonJS、SystemJS、ES6。
parser 属性可以更细粒度的配置哪些模块语法要解析哪些不解析,和 noParse 配置项的区别。在于 parser 可以精确到语法层面, 而 noParse 只能控制哪些文件不被解析。
Resolve(配置 Webpack 如何寻找模块所对应的文件)
alias:
resolve.alias
配置项通过别名来把原导入路径映射成一个新的导入路径。
mainFields:
有一些第三方模块会针对不同环境提供几分代码,Webpack
会根据 mainFields
的配置去决定优先采哪份代码。
extensions:
在导入语句没带文件后缀时,Webpack
会自动带上后缀后去尝试访问文件是否存在。 resolve.extensions
用于配置在尝试过程中用到的后缀列表。extensions: ['.ts', '.js', '.json']
modules:
resolve.modules
配置 Webpack
去哪些目录下寻找第三方模块,默认是只会去 node_modules
目录下寻找。 modules:['./src/components','node_modules']
descriptionFiles:
resolve.descriptionFiles
配置描述第三方模块的文件名称,也就是 package.json 文件。默认如下:descriptionFiles: ['package.json']
enforceExtension:
resolve.enforceExtension
如果配置为true
, 所有导入语句都必须要带文件后缀。 例如开启前 import './foo'
能正常工作,开启后就必须写成 import './foo.js'
。
enforceModuleExtension:
enforceModuleExtension
和 enforceExtension
作用类似,但 enforceModuleExtension
只对 node_modules
下的模块生效。
Plugin(用于扩展 Webpack 功能)
配置 Plugin:
plugins
配置项接受一个数组,数组里每一项都是一个要使用的 Plugin
的实例,Plugin
需要的参数通过构造函数传入。
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
module.exports = {
plugins: [
// 所有页面都会用到的公共代码提取到 common 代码块中
new CommonsChunkPlugin({
name: 'common',
chunks: ['a', 'b']
}),
]
};
devServer
只有在通过 DevServer
去启动 Webpack
时配置文件里 devServer
才会生效,因为这些参数所对应的功能都是 DevServer
提供的,Webpack
本身并不认识 devServer
配置项。
hot:
devServer.hot
配置是否启用模块热替换功能。
DevServer
默认的行为是在发现源代码被更新后会通过自动刷新整个页面来做到实时预览,开启模块热替换功能后将在不刷新整个页面的情况下通过用新模块替换老模块来做到实时预览。
inline:
DevServer
的实时预览功能依赖一个注入到页面里的代理客户端去接受来自 DevServer
的命令和负责刷新网页的工作。
- 如果开启
inline
,DevServer
会在构建完变化后的代码时通过代理客户端控制网页刷新。如果你想使用DevServer
去自动刷新网页实现实时预览,最方便的方法是直接开启inline
。 - 如果关闭
inline
,DevServer
将无法直接控制要开发的网页。这时它会通过iframe
的方式去运行要开发的网页,当构建完变化后的代码时通过刷新iframe
来实现实时预览。 但这时你需要去http://localhost:8080/webpack-dev-server/
实时预览你的网页了。
historyApiFallback:
单页应用要求服务器在针对任何命中的路由时都返回一个对应的 HTML
文件,浏览器端的 JavaScript
代码会从 URL
里解析出当前页面的状态,显示出对应的界面。
-
只有一个 HTML 文件的应用:
historyApiFallback: true
,任何请求都会返回index.html
文件。 -
由多个单页应用组成的应用:需要
DevServer
根据不同的请求来返回不同的HTML
文件,配置如下:
historyApiFallback: {
// 使用正则匹配命中路由
rewrites: [
// /user 开头的都返回 user.html
{ from: /^\/user/, to: '/user.html' },
{ from: /^\/game/, to: '/game.html' },
// 其它的都返回 index.html
{ from: /./, to: '/index.html' }
]
}
contentBase:
devServer.contentBase
配置 DevServer HTTP
服务器的文件根目录。 默认情况下为当前执行目录,通常是项目根目录。
contentBase
只能用来配置暴露本地文件的规则,可以通过 contentBase: false
来关闭暴露本地文件。
headers:
devServer.headers
配置项可以在 HTTP
响应中注入一些 HTTP
响应头。
host:
devServer.host
配置项用于配置 DevServer
服务监听的地址。
port:
devServer.port
配置项用于配置 DevServer
服务监听的端口,默认使用 8080
端口。
allowedHosts:
devServer.allowedHosts
配置一个白名单列表,只有 HTTP
请求的 HOST
在列表里才正常返回。
allowedHosts: [
// 匹配单个域名
'host.com',
'sub.host.com',
// host2.com 和所有的子域名 *.host2.com 都将匹配
'.host2.com'
]
disableHostCheck:
devServer. disableHostCheck
配置项用于配置是否关闭用于 DNS
重绑定的 HTTP
请求的 HOST
检查。 DevServer
默认只接受来自本地的请求,关闭后可以接受来自任何 HOST
的请求。
https:
DevServer
默认使用 HTTP
协议服务,它也能通过 HTTPS
协议服务。
devServer: {
https: true
}
clientLogLevel:
devServer. clientLogLevel
配置一个白名单列表,只有 HTTP
请求的 HOST
在列表里才正常返回。
clientLogLevel:
devServer. clientLogLevel
配置在客户端的日志等级,这会影响到你在浏览器开发者工具控制台里看到的日志内容。 clientLogLevel
是枚举类型,可取如下之一的值 none | error | warning | info
。 默认为 info
级别,即输出所有类型的日志,设置成 none
可以不输出任何日志。
compress:
devServer. compress
配置是否启用 gzip
压缩。默认为 false
。
open:
devServer. open
用于在 DevServer
启动且第一次构建完时自动用你系统上默认的浏览器去打开要开发的网页。 同时还提供 devServer.openPage
配置项用于打开指定 URL
的网页。
其它配置项
Target:
target
配置项可以让 Webpack
构建出针对不同运行环境的代码。
Devtool:
devtool
配置 Webpack
如何生成 Source Map
(以方便调试),默认值是 false
即不生成 Source Map
。
Watch 和 WatchOptions:
Webpack
的监听模式,它支持监听文件更新,在文件发生变化时重新编译。
在使用 Webpack
时监听模式默认是关闭的,在使用 DevServer
时,监听模式默认是开启的。
Externals:
Externals
用来告诉 Webpack
要构建的代码中使用了哪些不用被打包的模块,也就是说这些模版是外部环境提供的,Webpack
在打包时可以忽略它们。
通过 externals
可以告诉 Webpack JavaScript
运行环境已经内置了哪些全局变量,针对这些全局变量不用打包进代码中而是直接使用全局变量。
module.export = {
externals: {
// 把导入语句里的 jquery 替换成运行环境里的全局变量 jQuery
jquery: 'jQuery'
}
}
ResolveLoader:
ResolveLoader
用来告诉 Webpack
如何去寻找 Loader
,因为在使用 Loader
时是通过其包名称去引用的, Webpack
需要根据配置的 Loader
包名去找到 Loader
的实际代码,以调用 Loader
去处理源文件。
ResolveLoader
的默认配置如下,常用于加载本地的 Loader
。
module.exports = {
resolveLoader: {
// 去哪个目录下寻找 Loader
modules: ['node_modules'],
// 入口文件的后缀
extensions: ['.js', '.json'],
// 指明入口文件位置的字段
mainFields: ['loader', 'main']
}
}
总结
通常你可用如下经验去判断如何配置 Webpack
:
- 想让源文件加入到构建流程中去被
Webpack
控制,配置entry
。 - 想自定义输出文件的位置和名称,配置
output
。 - 想自定义寻找依赖模块时的策略,配置
resolve
。 - 想自定义解析和转换文件的策略,配置
module
,通常是配置module.rules
里的Loader
。 - 其它的大部分需求可能要通过
Plugin
去实现,配置plugin
。