前言
作为前端开发者,相信大家或多或少都接触过webpack,现如今webpack已经渗透在了前端的各个方面,所以我们有必要来了解并学习webpack,webpack 是一种用于构建 JavaScript 应用程序的静态模块打包器,它能够以一种相对一致且开放的处理方式,加载应用中的所有资源文件(图片、CSS、视频、字体文件等),并将其合并打包成浏览器兼容的 Web 资源文件。webpack相比其它构建工具功能更加强大,可扩展性也更强,它能够融合多种工程化工具,将开发阶段的应用代码编译、打包成适合网络分发、客户端运行的应用产物。
核心概念
输入输出
entry
webpack的构建入口,入口起点(entry point) 指示 webpack 应该使用哪个模块,来作为构建其内部 依赖图(dependency graph) 的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
// 单入口
module.exports = {
entry: './src/main.js'
}
// 多入口
module.exports = {
entry: {
a: './src/a.js',
b: './src/b.js'
}
}output
output 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。主要输出文件的默认值是./dist/main.js,其他生成文件默认放置在./dist文件夹中。
// 单入口
module.exports = {
entry: './src/main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
}
}
// 多入口
module.exports = {
entry: {
a: './src/a.js',
b: './src/b.js'
},
output: {
filename: '[name].[hash:6].js', // 通过占位符确保文件名唯一,考虑缓存问题,还可以为文件名加上hash
path: __dirname + '/dist',
publicPath: '/', // 生产环境一般是CDN地址,开发环境配置为/或不配置
}
}模块处理
loader
webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。
比如:配置webpack为css文件应用css-loader
module.exports = {
module: {
rules: [
{test: /.css$/, use: 'css-loader'}
]
}
}module.rules 允许你在 webpack 配置中指定多个 loader。 这种方式是展示 loader 的一种简明方式,并且有助于使代码变得简洁和易于维护。
plugin
插件 是 webpack 的 支柱 功能。Webpack 自身也是构建于你在 webpack 配置中用到的 相同的插件系统 之上!
比如:为编译过程添加进度报告插件
const Webpack = require('webpack')
module.exports = {
plugins: [new Webpack.ProgressPlugin()]
}resolve
用于配置模块路径解析规则,可用于帮助 Webpack 更精确、高效地找到指定模块
比如配置别名:
创建 import 或 require 的别名,来确保模块引入变得更简单。例如,一些位于 src/ 文件夹下的常用模块:
module.exports = {
resolve: {
alias: {
node_modules: path.resolve(__dirname, './node_modules'),
'@': path.resolve(__dirname, './src'),
api: path.resolve(__dirname, './src/api'),
components: path.join(__dirname, './src/components'),
}
}
}module
这些选项决定了如何处理项目中的不同类型的模块。
比如我们常见的loader就是在module.rules内配置的。
module.exports = {
module: {
rules: [
{test: /.css$/, use: 'css-loader'}
]
}
}externals
用于声明外部资源,Webpack 会直接忽略这部分资源,跳过这些资源的解析、打包操作
比如防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies) 。
比如:从CDN引入Vue
<!-- index.html -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.3/vue.min.js"></script>// webpack.config.js
module.exports = {
externals: {
vue: 'vue'
}
}后处理
optimization
用于控制如何优化产物包体积,内置 Dead Code Elimination、Scope Hoisting、代码混淆、代码压缩等功能
从 webpack 4 开始,会根据你选择的
mode来执行不同的优化, 不过所有的优化还是可以手动配置和重写。
module.exports = {
//...
optimization: {
chunkIds: 'named',
},
};target
用于配置编译产物的目标运行环境,支持 web、node、electron 等值,不同值最终产物会有所差异
比如:target设置为node,webpack将在node环境下进行编译
module.exports = {
target: 'node'
}mode
提供 mode 配置选项,告知 webpack 使用相应模式的内置优化。string = 'production': 'none' | 'development' | 'production'module.exports = {
mode: 'development',
};或者从cli--mode 参数进行传递
webpack --mode development开发效率
watch
启用 Watch 模式。这意味着在初始构建之后,webpack 将继续监听任何已解析文件的更改。
module.exports = {
watch: true
}⚠️注意:webpack-dev-server和webpack-dev-middleware默认是开启watch模式的
devtool
此选项控制是否生成,以及如何生成 source map。
string = 'eval' | false选择一种 source map 风格来增强调试过程。不同的值会明显影响到构建(build)和重新构建(rebuild)的速度。
devServer
用于配置与 HMR 强相关的开发服务器功能
通过 webpack-dev-server 的这些配置,能够以多种方式改变其行为,这里比较常见的配置有:port、host、proxy等
module.exports = {
devServer: {
static: {
directory: path.join(__dirname, 'public'),
},
compress: true,
port: 9000,
}
}cache
Webpack 5 之后,该项用于控制如何缓存编译过程信息与编译结果
缓存生成的 webpack 模块和 chunk,来改善构建速度。cache 会在开发 模式被设置成 type: 'memory' 而且在 生产 模式 中被禁用。 cache: true 与 cache: { type: 'memory' } 配置作用一致。 传入 false 会禁用缓存:
module.exports = {
cache: false
}上手配置
了解完上面这些webpack核心概念,我们可以尝试来手动配置好一个Vue开发环境
初始化项目
首先npm init -y初始化package.json文件
接着安装好我们的webpack、webpack-cli
npm i webpack webpack-cli -D⚠️注意: 我这里的webpack是5版本的
"webpack": "^5.85.1",
"webpack-cli": "^4.7.2",处理Vue代码
原生 Webpack 并不能处理这种内容格式的文件,为此我们需要引入专用于 Vue SFC 的加载器:vue-loader
npm i vue-loader