[toc]
webpack 这篇专栏文章介绍了 webpack 的概念与基础用法,并且介绍了常用的实际应用场景,相信看完后就可以搭建一套自己的 web 构建程序。1 概念
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
2 基础配置属性介绍
2.1 entry
打包的入口文件,打包时会根据入口文件找到项目的依赖,形成一棵依赖树。
2.1.1 单入口:
一个应用只有一个入口,适合单页应用。
module.exports = {
entry: './src/index.js'
}
2.1.2 多入口:
适合多页面应用,entry 是一个对象
module.exports = {
entry: {
app: './src/index.js',
home: './src/home.js',
}
}
2.2 output
设置打包的出口
参数:
- path: 打包后的文件目录。
- filename:打包后的文件名字。可以用
[name]
的形式对文件名占位
var path = require('path');
module.exports = {
entry: {
index: './src/index.js',
home: './src/home.js'
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].js',
}
}
2.3 loaders
webpack 本身只支持 js 和 json 两种文件类型,通过 loaders 去支持其他文件类型并且可以添加到依赖树中,比如 html、jsx、css、图片等。loaders 本身是一个函数,将文件输入并转换出想要的文件。
2.3.1 用法
参数:
- test:匹配规则
- loader:loader 名字
- exclude:排除规则
- query | options: loader 参数
modules.exports = {
module: {
rules: [
{
test: /\.css$/,
loader: 'style-loader!css-loader'
},
{ test: /\.tsx?$/,
loader: 'ts-loader'
},
{
test: /\.js?$/,
exclude: /(node_modules|packages)/, // 排除的目录
loader: 'babel-loader',
query: {presets: ['es2015', 'react']}} // 配置参数
]
},
};
2.3.2 常用的 loader
- babel-loader:转换es6、es7等新js语法
- css-loader: 支出 css 的加载解析,在页面中可以通过 import 的方式将 css 引入页面
- scss-loader:将 less 文件转换成 css
- ts-loader: 将 ts 转换为 js
- file-loader:进行图片、字体等文件的解析
- url-loader: 内置了 file-loader,可以设置 ‘limit’,当文件体积小于 limit 的时候将文件转成 DataURL,当大于 limit 的时候调用 file-loader 处理。
- raw-loader:将文件以字符串的形式导入
- thread-loader:使用多进程打包,用于打包速度优化处理耗时 loader
- cache-loader: 将其后面 loader 打包的结果缓存到磁盘
2.4 plugins
插件。打包过程中文件处理的一部分,添加打包过程中的各种功能。
2.4.1 用法
modules.exports = {
entry: {
index: './src/index.js'
},
plugins: [
new HtmlWebpackPlugin({template: './index.html'})
],
};
2.4.2 常用的 plugins
- Webpack-dev-server: 是一个express服务器,提供项目运行服务(自带热更新)
- CommonsChunkPlugin:将公用的js提取出来作为独立的的模块,webpack4.0中被 SplitChunksPlugin 替代
- CleanWebpackPlugin:清理构建目录
- ExtractTextWebpackPlugin:将 css 从 bundle 中提取出来作为独立的文件
- HtmlWebpackPlugin: 创建 html 文件并将打包后的文件插入进去
- speed-measure-webpack-plugin 构建时会列出各个 loader 和 plugin 消耗时间信息,可用于分析优化策略
- Happypack:使用多进程打包,用于打包速度优化
2.5 model
指定当前环境
值:
- production:线上环境。自动开启
FlagDependencyUsagePlugin、FlagIncludeChunksPlugin、ModuleCocatenationPlugin、NoemitOnErrorsPlugin、OccurrenceOrderPlugin、SideEffectsFlagPlugin、TerserPlugin
。自动对代码进行压缩、识别打包时副作用的参数等。 - development:开发环境。自动开启
NamedChunksPlugin、NamedModulesPlugin
。在 HMR 阶段在控制台打印更新的目录。 - none:不开启任何优化选项。
modules.exports = {
mode: 'production',
};
3 实际应用
3.1 以 npm 命令的形式运行 webpack
webpack 的运行命令一般比较长,如果参数比较多的话会更长,可以把 webpack 以 npm 命令的方式执行
- 将命令配置在
package.json
{
"scripts": {
"build": "webpack --config=./webpack.config.js",
}
}
- 使用的时候直接运行
npm run build
3.2 利用 babel 解析 es6 和 '.jsx'
需要用到
babel-loader
, 上面说过 loader 是用来处理输入文件然后转义成想要的输出文件的,这里以 转义es6
语法 与 react.jsx
语法为例。转义其他类型的文件如.scss
方式雷同,只不过 loader 与配置参数不一样
- 下载 babel 相关依赖
npm i -D @babel/core @babel/preset-env babel-loader
- 创建 babel的配置文件
.babelrc
(更多 babel 相关配置请看 babel 文档)
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
}
- 配置
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js(x?)$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
}
},
],
},
};
注: babel-loader 还支持不使用 .babelrc
,直接在 babel-loader
的参数中配置 babel, 下面的方式与上面的效果一样
module.exports = {
module: {
rules: [
{
test: /\.js(x?)$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
query: {
presets: ['env', 'react'],
}
}
},
],
},
};
3.3 将 js 自动以 <script/>
的形式插入 html
这里介绍的是 Plugin 的实际应用(plugin 的作用上面介绍过了),本示例中会用到
HtmlWebpackPlugin
- 下载 HtmlWebpackPlugin
npm i -D html-webpack-plugin
- 在
webpack.config.js
中引入并使用
每个模板页必须单独配置 HtmlWebpackPlugin,如果有多个页面就得使用多个
HtmlWebpackPlugin
, 下面示例配置了 'index' 与 'home' 两个文件的模板。
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: './src/index/index.jsx',
home: './src/home/home.jsx'
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name]/[name].[chunkhash:8].js'
},
plugins: [
new HtmlWebpackPlugin({
chunks:['index'], // 说明要加载的模块(不指定的话,index.js 与 home.js 都会引进来)
filename: 'index/index.html', // 输出位置与名字
template: 'src/index/index.html' // 模板位置
}),
new HtmlWebpackPlugin({
chunks:['home'],
filename: 'home/home.html',
template: 'src/home/home.html'
}),
],
}
注: 更多配置,请看 HtmlWebpackPlugin 文档
3.4 将 css 与 js 分离,并插入 html
默认 webpack 在打包的时候会将 css 打包进引用的 bundle.js 中, 我们可以用
ExtractTextWebpackPlugin
将 css 分离出来,以实现 js、html 与 css 的分离,与通用 css 复用的目的。下面的例子顺便介绍了 sass 的转译
- 下载 css 相关 loader 与 ExtractTextWebpackPlugin
npm i -D css-loader sass-loader extract-text-webpack-plugin
- webpack.config.js 配置
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: ExtractTextWebpackPlugin.extract({
use: [
{loader: 'css-loader'},
{loader: 'sass-loader'},
],
}),
},
],
},
plugins: [
new ExtractTextWebpackPlugin({
allChunks: true,
filename: '[name]/[name].[hash:8].css',
}),
],
}
注: 上面的例子对 .scss
文件进行了转译,并且在在输出的 css 文件后加了 hash 值(每次修改 css 都会变,避免缓存)。编译后的 css 文件会以 <link/>
的形式插入 html
3.5 本地 server 开发 && 热更新
使用
webpack-dev-server
可以在本地启动 node server 并启一个端口,同时其默认开启热更新以便在开发过程中实时观看代码修改的效果
- 下载 webpack-dev-server
npm i -D webpack-dev-server
- 配置 webpack.config.js
module.exports = {
devServer: {
index: 'index/index.html', // 入口文件
contentBase: [path.join(__dirname, 'dist')], // 打包后的资源目录
compress: true,
port: 9000 // 端口
}
}
- 在 package.json 配置 npm 命令, 并启动
{
"scripts": {
"start": "webpack-dev-server"
},
}
注: webpack-dev-server 还支持函数式的使用方式,以在运行过程中提供更灵活的配置。详情见文档
5 性能优化
待续。。。
6 编写自己的 loader
待续。。。
接下来会将会深入介绍 webpack 的原理、我在实际工作中遇到的问题与性能优化、并亲手写一个属于自己的 loader。这些文章应该会单独启一篇,到时候会将链接贴在这。喜欢的小伙伴可以比心并持续关注哦