Webpack是一个前端工程化的工具,那么首先,什么是前端工程化?
前端工程化
近年来前端领域的高速发展,使得我们前端工作者可以做的事情越来越多,而项目也不可避免的越来越大,这时便需要多个人协同开发,为了保证高效的开发,前端工程需要变得组件化、模块化、自动化、规范化。而Webpack就是帮助前端工程化的重要工具。
Webpack的优点
- 将多个文件资源合并,减少HTTP请求数
- 支持模块化开发
- 支持高级JS特性
- 统一图片、CSS、字体等资源的处理模型
- ...
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 里定义的逻辑。
Loader
Webpack如此重要,可它却只认得JS,那该怎么办呢,这个时候便需要配置Loader来帮助它将其他语言翻译为JS了,示例如下
const path = require('path');
module.exports = {
// JavaScript 执行入口文件
entry: './main.js',
output: {
// 把所有依赖的模块合并输出到一个 bundle.js 文件
filename: 'bundle.js',
// 输出文件都放到 dist 目录下
path: path.resolve(__dirname, './dist'),
},
module: {
rules: [
{
// 用正则去匹配要用该 loader 转换的 CSS 文件
test: /.css$/,
use: ['style-loader', 'css-loader?minimize'],
}
]
}
};
Loader 可以看作具有文件转换功能的翻译员,配置里的 module.rules 数组配置了一组规则,告诉 Webpack 在遇到哪些文件时使用哪些 Loader 去加载和转换。 如上配置告诉 Webpack 在遇到以 .css 结尾的文件时先使用 css-loader 读取 CSS 文件,再交给 style-loader 把 CSS 内容注入到 JavaScript 里。 在配置 Loader 时需要注意的是:
use属性的值需要是一个由 Loader 名称组成的数组,Loader 的执行顺序是由后到前的;- 每一个 Loader 都可以通过 URL querystring 的方式传入参数,例如
css-loader?minimize中的minimize告诉css-loader要开启 CSS 压缩。
应用实例
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
entry: './src/index.js',
mode: 'development', // 会将 `process.env.NODE_ENV` 的值设为 `development`
devtool: 'eval-source-map', // 将会生成source-map
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist_[hash]'), //通常通过 Node.js的path模块去获取绝对路径
},
module: {
rules: [{
test: /\.vue$/i,
loader: 'vue-loader'
}, {
test: /\.(le|c)ss/i,
use: ['vue-style-loader', 'style-loader', 'css-loader', 'less-loader']
}, {
test: /\.ts$/i,
exclude: /node_modules/, //排除该目录下的文件
use: { loader: 'ts-loader' }
}, {
test: /\.js$/i,
use: [{
loader: 'babel-loader',
options: {
presets: [[ '@babel/preset-env' ]] //传一些参数
}
}]
}]
},
devServer: {
hot: true, //开启热编译
open: true
},
resolve: {
extensions: ['.ts', '.js']
},
plugins: [new VueLoaderPlugin(), new HtmlWebpackPlugin()] } //添加插件