webpack核心
- entry:入口,构建从入口开始
- module:模块,在webpack中一个模块就是一个文件
- chunk:代码块,多个模块集合,方便合并分割
- loader:模块转换器,用于将模块按照需求转换
- Plugin:扩展插件,在Webpack构建流程中的特定时机注入扩展逻辑,来改变构建结果或做我们想要的事情。
- Output:输出结果,在Webpack经过一系列处理并得出最终想要的代码后输出结果。Webpack在启动后会从Entry里配置的Module开始,递归解析Entry依赖的所有Module。
遇到问题汇总
- 文件夹名称不能使用webpack
- 当使用webpacck4.0时
extract-text-webpack-plugin
这个插件(为css生产单文件)必须使用^4.0.0-bet.0
版本 - 在开启热启动,开发服务器,sourcemap时要这么写
webpack-dev-server --config--hot--devtool source-map --config webpack.config.js
不然会报错 - webpack4.0使用
hash
去替代contenthash
webpack配置
webpack有如下两种配置方式
- 通过一个JavaScript文件描述配置,例如使用webpack.config.js文件里的配置;
- 执行Webpack可执行文件时通过命令行参数传入,例如webpack–devtoolsource-map。
按照配置所影响的功能来划分,可分为如下内容。
Entry
配置模块的入口,webpack将从入口递归解析出所有的依赖模块
entery是必填项,否则会导致webpack报错退出
context
webpack在寻找相对路径文件时会以context为根目录,默认下context为webpack命令执行目录,可以通过如下方法改变:
1 | module.export = { |
context必须为绝对路径,也可以在启动时使用webpack --context
来设置
entry类型
可以是字符串,数组和对象
- 字符串
'./app/entry'
入口模块的文件路径,可以是相对路径。 - 数组
['./app/entry1', './app/entry2']
入口模块的文件路径,可以是相对路径。
如果是 array 类型,则搭配 output.library 配置项使用时,只有数组里的最后一个入口文件的模块会被导出。 - 对象
{ a: './app/entry-a', b: ['./app/entry-b1', './app/entry-b2']}
配置多个入口,每个入口生成一个 Chunk
##### chuck名称 Webpack会为每个生成的Chunk取一个名称,Chunk的名称和Entry的配置有关。 如果entry是一个string或array,就只会生成一个Chunk,这时Chunk的名称是main。 如果entry是一个object,就可能会出现多个Chunk,这时Chunk的名称是object键值对中键的名称。
##### 动态entry
1 | // 同步 |
后两者可以通过[hash:n]来指定长度,n为长度
##### chuckfilename 用来配置无入口的chuck名称
##### path 用来配置输出路径,必须是绝对路径
1 | path: path.resolve(__dirname,'dist[hash]') |
##### publicpath 在复杂的项目里可能会有一些构建出的资源需要异步加载,加载这些异步资源需要对应的URL地址。output.publicPath配置发布到线上资源的URL前缀,为string类型。默认值是空字符串'',即使用相对路径。 比如需要将构建出的资源文件上传到CDN服务上,以利于加快页面的打开速度。
1 | filename:'[name]_[chunkhash:8].js' |
1 | <script src='https://cdn.example.com/assets/a_12345678.js'></script> |
1 | // Webpack 输出的代码(output.library='LibraryName') |
1 | // Webpack 输出的代码 |
1 | // Webpack 输出的代码 |
1 | // Webpack 输出的代码 |
1 | // Webpack 输出的代码 |
##### libraryExport `output.libraryExport`配置要导出的模块中哪些子模块需要被导出。 它只有在`output.libraryTarget`被设置成`commonjs`或者`commonjs2`时使用才有意义。 需要导出的模块
1 | export const a=1; |
1 | // Webpack 输出的代码 |
##### 配置Loader `rules`配置模块的读取和解析规则,通常用来配置`Loader`。其类型是一个数组,数组里每一项都描述了如何去处理部分文件。配置一项`rules`时大致通过以下方式:
- 条件匹配:通过 test 、 include 、 exclude 三个配置项来命中 Loader 要应用规则的文件。
- 应用规则:对选中后的文件通过 use 配置项来应用 Loader,可以只应用一个 Loader 或者按照从后往前的顺序应用一组 Loader,同时还可以分别给 Loader 传入参数。
- 重置顺序:一组 Loader 的执行顺序默认是从右到左执行,通过 enforce 选项可以让其中一个 Loader 的执行顺序放到最前或者最后。
下面来通过一个例子来说明具体使用方法:
1 | module: { |
在 Loader 需要传入很多参数时,你还可以通过一个 Object 来描述,例如在上面的 babel-loader 配置中有如下代码:
1 | use: [ |
上面的例子中test include exclude
这三个命中文件的配置项只传入了一个字符串或正则,其实它们还都支持数组类型,使用:
1 | { |
数组里的每项之间是或的关系,即文件路径符合数组中的任何一个条件就会被命中。
noParse
noParse
配置项可以让Webpack忽略对部分没采用模块化的文件的递归解析和处理,这样做的好处是能提高构建性能。原因是一些库例如jQuery、ChartJS它们庞大又没有采用模块化标准,让Webpack去解析这些文件耗时又没有意义。noParse
是可选配置项,类型需要是RegExp、[RegExp]、function
其中一个。
例如想要忽略掉 jQuery 、ChartJS,可以使用如下代码:
1 | // 使用正则表达式 |
注意被忽略掉的文件里不应该包含
import
、require
、define
等模块化语句,不然会导致构建出的代码中包含无法在浏览器环境下执行的模块化语句。
##### parser 因为 Webpack 是以模块化的 JavaScript 文件为入口,所以内置了对模块化 JavaScript 的解析功能,支持 AMD、CommonJS、SystemJS、ES6。 `parser`属性可以更细粒度的配置哪些模块语法要解析哪些不解析,和`noParse`配置项的区别在于`parser`可以精确到语法层面,而`noParse`只能控制哪些文件不被解析。`parser`使用如下:
1 | module: { |
以上alias
配置的含义是把导入语句里的components
关键字替换成./src/components/
。
这样做可能会命中太多的导入语句,alias
还支持$
符号来缩小范围到只命中以关键字结尾的导入语句:
1 | resolve:{ |
react$
只会命中以react
结尾的导入语句,即只会把import 'react'
关键字替换成import '/path/to/react.min.js'
。
mainFields
有一些第三方模块会针对不同环境提供几分代码。 例如分别提供采用 ES5 和 ES6 的2份代码,这2份代码的位置写在package.json
文件里,如下:
1 | { |
Webpack会根据mainFields
的配置去决定优先采用那份代码,mainFields
默认如下:
1 | mainFields: ['browser', 'main'] |
Webpack 会按照数组里的顺序去package.json
文件里寻找,只会使用找到的第一个。
假如你想优先采用 ES6 的那份代码,可以这样配置:
1 | mainFields: ['jsnext:main', 'browser', 'main'] |
##### extensions 在导入语句没带文件后缀时,Webpack 会自动带上后缀后去尝试访问文件是否存在。`resolve.extensions`用于配置在尝试过程中用到的后缀列表,默认是:
1 | extensions: ['.js', '.json'] |
假如你想让 Webpack 优先使用目录下的 TypeScript 文件,可以这样配置:
1 | extensions: ['.ts', '.js', '.json'] |
modules
resolve.modules
配置Webpack去哪些目录下寻找第三方模块,默认是只会去node_modules
目录下寻找。有时你的项目里会有一些模块会大量被其它模块依赖和导入,由于其它模块的位置分布不定,针对不同的文件都要去计算被导入模块文件的相对路径,这个路径有时候会很长,就像这样import '../../../components/button'
这时你可以利用modules
配置项优化,假如那些被大量导入的模块都在./src/components
目录下,把modules
配置成
1 | modules:['./src/components','node_modules'] |
后,你可以简单通过import 'button'
导入。
descriptionFiles
resolve.descriptionFiles
配置描述第三方模块的文件名称,也就是package.json
文件。默认如下:
1 | descriptionFiles: ['package.json'] |
enforceExtension
resolve.enforceExtension
如果配置为true
所有导入语句都必须要带文件后缀,例如开启前import './foo'
能正常工作,开启后就必须写成import './foo.js'
。
enforceExtension
resolve.enforceExtension
如果配置为true
所有导入语句都必须要带文件后缀,例如开启前import './foo'
能正常工作,开启后就必须写成import './foo.js'
。
enforceModuleExtension
enforceModuleExtension
和enforceExtension
作用类似,但enforceModuleExtension
只对node_modules
下的模块生效。enforceModuleExtension
通常搭配enforceExtension
使用,在enforceExtension:true
时,因为安装的第三方模块中大多数导入语句没带文件后缀,所以这时通过配置enforceModuleExtension:false
来兼容第三方模块。
optimization
从webpack4开始webpack会根据你设置的mode运行优化,所有的优化都可以被手工配置或覆盖。
optimization.minimize
boolean
webpack会使用UglifyjsWebpackPlugin
对包进行最小化。
在production
模式下这个值默认为true
1 | module.exports = { |
##### optimization.splitChunks `object` 默认情况下,webpack为动态引入的模块提供了新的开箱即用的通用块策略。
DevServer:配置DevServer
要配置 DevServer ,除了在配置文件里通过devServer
传入参数外,还可以通过命令行参数传入。 注意只有在通过 DevServer 去启动 Webpack 时配置文件里devServer
才会生效,因为这些参数所对应的功能都是 DevServer 提供的,Webpack 本身并不认识devServer
配置项。
hot
devServer.hot
配置是否启用 1-6 使用DevServer 中提到的模块热替换功能。 DevServer 默认的行为是在发现源代码被更新后会通过自动刷新整个页面来做到实时预览,开启模块热替换功能后将在不刷新整个页面的情况下通过用新模块替换老模块来做到实时预览。
inline
DevServer 的实时预览功能依赖一个注入到页面里的代理客户端去接受来自 DevServer 的命令和负责刷新网页的工作。 devServer.inline
用于配置是否自动注入这个代理客户端到将运行在页面里的 Chunk 里去,默认是会自动注入。 DevServer 会根据你是否开启inline
来调整它的自动刷新策略:
如果开启
inline
,DevServer 会在构建完变化后的代码时通过代理客户端控制网页刷新。如果关闭
inline
,DevServer 将无法直接控制要开发的网页。这时它会通过 iframe 的方式去运行要开发的网页,当构建完变化后的代码时通过刷新 iframe 来实现实时预览。 但这时你需要去http://localhost:8080/webpack-dev-server/
实时预览你的网页了。如果你想使用 DevServer 去自动刷新网页实现实时预览,最方便的方法是直接开启 inline。
##### historyApiFallback `devServer.historyApiFallback`用于方便的开发使用了`HTML5 History API`的单页应用。这类单页应用要求服务器在针对任何命中的路由时都返回一个对应的`HTML`文件,例如在访问`http://localhost/user`和`http://localhost/home`时都返回`index.html`文件,浏览器端的 JavaScript 代码会从`URL`里解析出当前页面的状态,显示出对应的界面。
配置historyApiFallback
最简单的做法是:
1 | historyApiFallback: true |
这会导致任何请求都会返回index.html
文件,这只能用于只有一个 HTML 文件的应用。
如果你的应用由多个单页应用组成,这就需要 DevServer 根据不同的请求来返回不同的 HTML 文件,配置如下:
1 | historyApiFallback: { |
##### contentBase `devServer.contentBase`配置 DevServer HTTP 服务器的文件根目录。 默认情况下为当前执行目录,通常是项目根目录,所有一般情况下你不必设置它,除非你有额外的文件需要被 DevServer 服务。 例如你想把项目根目录下的`public`目录设置成 DevServer 服务器的文件根目录,你可以这样配置:
1 | devServer:{ |
- 暴露本地文件。
- 暴露 Webpack 构建出的结果,由于构建出的结果交给了 DevServer,所以你在使用了 DevServer 时在本地找不到构建出的文件。
contentBase
只能用来配置暴露本地文件的规则,你可以通过contentBase:false
来关闭暴露本地文件。
headers
devServer.headers
配置项可以在 HTTP 响应中注入一些 HTTP 响应头,使用如下:
1 | devServer:{ |
##### host `devServer.host`配置项用于配置 DevServer 服务监听的地址。 例如你想要局域网中的其它设备访问你本地的服务,可以在启动 DevServer 时带上`--host 0.0.0.0`。`host`的默认值是`127.0.0.1`即只有本地可以访问 DevServer 的 HTTP 服务。
##### port `devServer.port`配置项用于配置 DevServer 服务监听的端口,默认使用 8080 端口。 如果 8080 端口已经被其它程序占有就使用 8081,如果 8081 还是被占用就使用 8082,以此类推。
##### allowedHosts `devServer.allowedHosts`配置一个白名单列表,只有 HTTP 请求的 HOST 在列表里才正常返回,使用如下:
1 | allowedHosts: [ |
##### disableHostCheck `devServer.disableHostCheck` 配置项用于配置是否关闭用于 DNS 重绑定的 HTTP 请求的 HOST 检查。 DevServer 默认只接受来自本地的请求,关闭后可以接受来自任何 HOST 的请求。 它通常用于搭配 `--host 0.0.0.0` 使用,因为你想要其它设备访问你本地的服务,但访问时是直接通过 IP 地址访问而不是 HOST 访问,所以需要关闭 HOST 检查。
##### https DevServer 默认使用 HTTP 协议服务,它也能通过 HTTPS 协议服务。 有些情况下你必须使用 HTTPS,例如 HTTP2 和 Service Worker 就必须运行在 HTTPS 之上。 要切换成 HTTPS 服务,最简单的方式是:
1 | devServer:{ |
如果你想用自己的证书可以这样配置:
1 | devServer:{ |
##### clientLogLevel `devServer.clientLogLevel`配置在客户端的日志等级,这会影响到你在浏览器开发者工具控制台里看到的日志内容。 `clientLogLevel`是枚举类型,可取如下之一的值`none | error | warning | info`。 默认为`info`级别,即输出所有类型的日志,设置成`none`可以不输出任何日志。
##### compress `devServer.compress`配置是否启用 gzip 压缩。`boolean`为类型,默认为`false`。
##### open `devServer.open`用于在 DevServer 启动且第一次构建完时自动用你系统上默认的浏览器去打开要开发的网页。 同时还提供`devServer.openPage`配置项用于打开指定 URL 的网页。
其他配置项:其他零散的配置项。
#前端/工具/webpack