Table of Contents
核心概念
Entry: 入口
Output: 输出结果
Module: 模块,webpack 中一切皆是模块
Loader: 模块转换器,用于把模块原内容按照需求转换成新内容
Plugin: 扩展插件,在 webpack 构建流程中的特定时机注入扩展逻辑来改变构建结果或做你想要做的事情
loader
从右到左,链式执行
上一个 Loader 的处理结果给下一个接着处理
node module 写法
module 依赖
return && this.callback()
路径
webpack 中查找 loader 的路径
loader 的绝对路径
设置 loader 的别名
设置 loader 的查找模块
1 | const path = require('path') |
顺序
webpack 中 loader 的默认执行顺序是从下到上,从右向左执行
enforce
调用的优先级(权重),调整调用顺序
顺序:前置(pre) > 普通(normal) > 行内(inline) > 后置(post)
1 | // -! 不会执行之前的 pre 和 normal loader 的处理 |
1 | module.exports = { |
Pitch loader
pitch 方法在 Loader 中便是从左到右执行的,并且可以通过 data 这个变量来进行 pitch 和 normal 之间传递。熔断功能
正常顺序:
1 | |- a-loader `pitch` |
设置 b-loader
的 pitch 函数
1 | // b-loader.js |
设置之后的顺序:
1 | |- a-loader `pitch` |
raw loader
默认的情况,原文件是以 UTF-8 String 的形式传入给 Loader,而在上面有提到的,module 可使用 buffer 的形式进行处理,针对这种情况,只需要设置 module.exports.raw = true; 这样内容将会以 raw Buffer 的形式传入到 loader 中了
1 | module.exports = function(source) { |
loader context
loader 中的上下文 this
data: pitch loader 中可以通过 data 让 pitch 和 normal module 进行数据共享。
query: 则能获取到 Loader 上附有的参数。 如 require(“./somg-loader?ls”); 通过 query 就可以得到 “ls” 了。
emitFile: emitFile 能够让开发者更方便的输出一个 file 文件,这是 webpack 特有的方法,使用的方法也很直接
1 | module.exports = function(source) { |
awesome
name | description | link |
---|---|---|
html-loader | 处理 html 中的资源引用 | GitHub |
url-loader | 处理资源文件,image、video 等 | GitHub |
file-loader | 处理资源文件,image、video 等 | GitHub |
babel-loader | es+ 转 es5 | GitHub |
plugin
webpack 中的 plugin 必须是一个
class
,且拥有apply
方法webpack 打包时会自动调用
plugin
实例的apply
方法,并传递compiler
参数compiler
上有个hooks
属性(钩子函数),plugin 就是基于钩子函数来做处理
server
proxy
简单的代理请求到目标域
1 | module.exports = { |
hook
webpack 中使用 express server
webpack dev server 是基于 express 构建的,它提供一个钩子函数 before
在参数中将 express app 暴露出来,用户可以自定义添加路由,模拟数据等
1 | module.exports = { |
webpack-dev-middleware
用户自定义的 server 中使用 webpack
1 | const webpack = require('webpack') |
全局变量
expose-loader
通过 expose-loader
将 import 的模块暴露到全局 window
上
loader 中配置
1 | module.exports = { |
內联形式
1 | import $ from 'expose-loader?$!jquery' |
Webpack.ProvidePlugin
通过 new Webpack.ProvidePlugin()
, 给每个模块文件直接注入一个模块,其他模块文件无需引用,直接调用
1 | module.exports = { |
externals
通过 script
在 html 引用,webpack 中设置 externals
直接使用外部引用,不打包进项目
1 | // webpack.config.js |
优化
module.noParse
不解析正则匹配的文件内部的 import
, require
, define
等
noParse 配置项可以让 Webpack 忽略对部分没采用模块化的文件的递归解析和处理,这样做的好处是能提高构建性能。 原因是一些库例如 jQuery lodash 它们庞大又没有采用模块化标准,让 Webpack 去解析这些文件耗时又没有意义。
1 | module.exports = { |
Webpack.IgnorePlugin
Webpack.IgnorePlugin webpack 自带的插件
比如 moment 库中的语言包很大,使用 IgnorePlugin
在 moment 中任何以 ‘./locale’ 结尾的 require
都将被忽略
1 | new webpack.IgnorePlugin({ |
用户需自行引入语言包
1 | import moment from 'moment' |
Webpack.DllPlugin
DllPlugin 是基于 Windows 动态链接库(dll)的思想被创作出来的。这个插件会把第三方库单独打包到一个文件中,这个文件就是一个单纯的依赖库。这个依赖库不会跟着你的业务代码一起被重新打包,只有当依赖自身发生版本变化时才会重新打包。
用 DllPlugin 处理文件,需要两步
基于 dll 专属的配置文件,打包 dll 库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// webpack.dll.js
const path = require('path')
const Webpack = require('webpack')
const resolve = (...dir) => path.resolve(__dirname, ...dir)
module.exports = {
mode: 'development',
entry: {
react: ['react', 'react-dom']
},
output: {
filename: '_dll_[name].js', // 产生的文件名
path: resolve('dist'),
library: '_dll_[name]'
},
plugins: [
// name要等于library里的name
new Webpack.DllPlugin({
name: '_dll_[name]',
path: resolve('dist', 'manifest.json')
})
]
}基于 webpack.config.js 文件,打包业务代码
1 | const path = require('path') |
happypack
多线程打包 - GitHub
1 | // webpack.config.js |
Tree-Shaking
webpack 自带 Tree-Shaking, scope hosting
1 | // scope hosting 作用域提升,去除无用代码 |
基于 import/export 语法,Tree-Shaking 可以在编译的过程中获悉哪些模块并没有真正被使用,这些没用的代码,在最后打包的时候会被去除。适合于处理模块级别的代码,所以尽量使用 es6 的 import/export 语法。
SplitChunksPlugin
1 | // 默认设置 |
dynamic imports
import() 还在草案中,需要 @babel/plugin-syntax-dynamic-import 才能使用
通过 es6 的 import 实现按需加载,在使用 import() 分割代码后,你的浏览器并且要支持 Promise API 才能让代码正常运行, 因为 import() 返回一个 Promise,它依赖 Promise。对于不原生支持 Promise 的浏览器,你可以注入 Promise polyfill。
1 | // dynamic imports |
HMR - Hot Module Replacement
模块热替换(HMR - Hot Module Replacement)是 webpack 提供的最有用的功能之一。它允许在运行时替换,添加,删除各种模块,而无需进行完全刷新重新加载整个页面
启用 HRM
new webpack.HotModuleReplacementPlugin()
devServer 选项中的 hot 字段为 true
1 | const path = require('path') |