记录Webpack基本配置规则;根据场景、技术栈运用具体方法、工具与技巧。
主要有:搭建完善的JavaScript、CSS开发环境;搭建微前端、NPM包、桌面应用等。
Webpak原生配置项数不胜数,最终都会作用于不同阶段
大致编译流程可分为四个流程:
输入—>模块处理—>后处理—>输出
Webpack配置项可分为两大类
与流程类配置强相关配置有:
entry
:用于定义项目入口文件,Webpack 会从这些入口文件开始按图索骥找出所有项目文件;context
:项目执行上下文路径;output
:配置产物输出路径、名称等;resolve
:用于配置模块路径解析规则,可用于帮助 Webpack 更精确、高效地找到指定模块module
:用于配置模块加载规则,例如针对什么类型的资源需要使用哪些 Loader 进行处理externals
:用于声明外部资源,Webpack 会直接忽略这部分资源,跳过这些资源的解析、打包操作optimization
:用于控制如何优化产物包体积,内置 Dead Code Elimination、Scope Hoisting、代码混淆、代码压缩等功能target
:用于配置编译产物的目标运行环境,支持 web、node、electron 等值,不同值最终产物会有所差异mode
:编译模式短语,支持 development、production 等值,可以理解为一种声明环境的短语Webpack 首先需要根据输入配置(
entry/context
) 找到项目入口文件;之后根据按模块处理(module/resolve/externals
等) 所配置的规则逐一处理模块文件,处理过程包括转译、依赖分析等;模块处理完毕后,最后再根据后处理相关配置项(optimization/target
等)合并模块资源、注入运行时依赖、优化产物结构等。
除了核心的打包功能之外,Webpack 还提供了一系列用于提升研发效率的工具,大体上可划分为:
watch
:用于配置持续监听文件变化,持续构建devtool
:用于配置产物 Sourcemap(储存代码转换前后的对应位置信息) 生成规则devServer
:用于配置与 HMR(模块热更新) 强相关的开发服务器功能cache
:Webpack 5 之后,该项用于控制如何缓存编译过程信息与编译结果 performance
:用于配置当产物大小超过阈值时,如何通知开发者stats
:用于精确地控制编译过程的日志内容,在做比较细致的性能调试时非常有用infrastructureLogging
:用于控制日志输出方式,例如可以通过该配置将日志输出到磁盘文件文件结构如下:
.
├── src
| └── index.js
└── webpack.config.js
其中,
src/index.js
为项目入口文件,webpack.config.js
为 Webpack 配置文件。在配置文件中,首先我们需要声明项目入口:
// webpack.config.js
module.exports = {
entry: "./src/index"
};
声明产物输出路径:
// webpack.config.js
const path = require("path");
module.exports = {
entry: "./src/index",
output: {
filename: "[name].js",
path: path.join(__dirname, "./dist"),
}
};
在前端项目中经常需要处理 JS 之外的其它资源,包括 css、ts、图片等,此时需要为这些资源配置适当的加载器:
// webpack.config.js
const path = require("path");
module.exports = {
entry: "./src/index",
output: {
filename: "[name].js",
path: path.join(__dirname, "./dist"),
},
module: {
rules: [{
test: /\.less$/i,
include: {
and: [path.join(__dirname, './src/')]
},
use: [
"style-loader",
"css-loader",
// "./loader",
{
loader: "less-loader",
},
],
}],
},
};
对于项目的推进,配置管理将十分困难。所以社区提供了对应的脚手架工具来管理配置。
Vue CLI 底层调用 Webpack 实现针对 .vue 等资源的编译打包功能;调用 webpack-dev-server 实现包含 HMR 功能的开发服务器功能;还能通过插件方式整合 ESLint、Babal、Less 等工具。
安装依赖:(安装完成后 可以使用 vue -V 测试是否安装成功)
npm install -g @vue/cli
# 或者使用 yarn
yarn global add @vue/cli
创建项目:
vue create
命令 (可使用vue create --help
命令查看 create 的参数列表仅限于 vue3中使用
)
vue create 项目名
执行 create 命令后,CLI 会进一步询问使用何种脚手架方案:
通常使用第三种自定义
Vue CLI v4.5.15
? Please pick a preset: (Use arrow keys)
❯ Default ([Vue 2] babel, eslint)
Default (Vue 3) ([Vue 3] babel, eslint)
Manually select features
vue2使用
vue init webpack 项目名
来构建项目
基本回车就行倒数四项根据自身需求来
Project name webpack5-dispose
? Project description A Vue.js project
? Author xxx <邮箱>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? No
? Set up unit tests No
? Setup e2e tests with Nightwatch? No
? Should we run `npm install` for you after the project has been created? (recommended) yarn
Vue CLI 底层依赖于 Webpack 实现编译打包等工程化能力,开发者可通过
configureWebpack
与chainWebpack
配置项修改 Webpack 配置信息。
// vue.config.js
module.exports = {
configureWebpack: {
plugins: [
new MyAwesomeWebpackPlugin()
]
}
}
configureWebpack 的配置规则与 Webpack 一致,同样支持 plugins/module/resolve 等配置项。实际上,Vue CLI 内部最终会调用 webpack-merge 将 configureWebpack 值与其它上下文配置合并,生成最终的 Webpack 配置信息。
// vue.config.js
module.exports = {
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.tap(options => {
// modify the options...
return options
})
}
}
使用 inspect 命令生成完整的 Webpack 配置信息:
vue inspect > output.js
使用如下代码可使用CRA创建一个react项目,webStrom创建react项目时可选CRA创建项目
npx create-react-app [项目名称]
默认规则创建的脚手架包含如下工程能力:
必要时,也可以通过
npm run eject
命令导出完整的项目配置结构:
注意:可能有未被管理的文件需要先提交在使用该命令
会生成对应的配置:
导出配置后,直接修改
webpack.config.js
等相关配置文件即可控制各项功能行为。
作用:用于将代码向后兼容,在旧版本JS引擎中运行
因为ES6提供了许多JS新特性,这就会导致旧版本的JS和Node等产生兼容性问题,Babel就是解决这个问题,它会将代码转译成旧版本的代码,使得旧版本引擎能正常使用。
// 使用 Babel 转译前
arr.map(item => item + 1)
// 转译后
arr.map(function (item){
return item + 1;
})
Webpack 场景下,只需使用
babel-loader
即可接入 Babel 转译功能:
npm i -D @babel/core @babel/preset-env babel-loader
module.exports = {
/* ... */
module: {
rules: [
{
test: /\.js$/, // 规则 表示所有.js后缀文件
use: ['babel-loader'], // 使用babel-loader处理
},
],
},
};
npx webpack
// 预先安装 @babel/preset-env
// npm i -D @babel/preset-env
module.exports = {
/* ... */
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
],
},
],
},
};
@babel/preset-env是Babel预设规则集----Preset,可以使用各种Preset资源:
babel-preset-react
:包含 React 常用插件的规则集,支持 preset-flow
、syntax-jsx
、transform-react-jsx
等;@babel/preset-typescript
:用于转译 TypeScript 代码的规则集@babel/preset-flow
:用于转译 Flow 代码的规则集在文件
build/webpack.base.conf.js
中脚手架已经配置了相关的配置项,但我们依然可以在
webpack.config.js中修改一些配置
entry`入口文件
entry: {
app: './src/main.js'
},
output
编译产物的目标位置
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'// 判断是什么环境
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve
解析规则
resolve: {
extensions: ['.js', '.vue', '.json'],//文件扩展名
alias: {// 别名
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
modele
解析模块
module: {
rules: [
{
test: /\.vue$/, // 规则过滤条件,这里表示对所有 .vue 后缀文件
loader: 'vue-loader',// vue-loader处理
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
在
config/webpack.config.js
中已经有脚手架给我门配置的一些
module: {
rules: [
{
test: /\.js$/,// 声明该规则过滤文件,只有路径和文件类型对应才会生效,此处为所有的 .js 后缀的文件生效
loader: 'babel-loader',// 所有命中文件传入Loader序列做转译
include: [resolve('src'), resolve('test'), //包内容路径 这里时src和test下的文件
resolve('node_modules/webpack-dev-server/client')]// 以及node_modules中自己的包
}
]
}
不光配置了程序内的文件,还配置了文件外
{
test: /\.(js|mjs)$/,
exclude: /@babel(?:\/|\\{1,2})runtime/,
loader: require.resolve('babel-loader'),
options: {
babelrc: false,
configFile: false,
compact: false,
presets: [
[
require.resolve('babel-preset-react-app/dependencies'),
{ helpers: true },
],
],
cacheDirectory: true,
// See #6846 for context on why cacheCompression is disabled
cacheCompression: false,
// Babel sourcemaps are needed for debugging into node_modules
// code. Without the options below, debuggers like VSCode
// show incorrect code and set breakpoints on the wrong lines.
sourceMaps: shouldUseSourceMap,
inputSourceMap: shouldUseSourceMap,
},
},
作用:提供了一系列类型约束,能更早的发现错误,确保运行阶段的类型安全性,适合在多人协作的项目中使用。
Webpack 有很多种接入 TypeScript 的方法,包括
ts-loader
、awesome-ts-loader
、babel-loader
。通常可使用ts-loader
构建 TypeScript 代码:
Vue CLi和 CRA均使用
babel-loader
引入TypeScript
npm i -D @babel/preset-typescript
// 预先安装 @babel/preset-env
// npm i -D @babel/preset-env
module.exports = {
/* ... */
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-typescript'],
},
},
],
},
],
},
};
@babel/preset-typescript
只是做了简单的代码转换,未做类型检查等,可以使用其它Preset
js作为一种灵活、弱类型脚本语言,对于一些开发过程中产生的语法、类型导致影响稳定的错误,这对开发效率和质量造成影响,ESLint就是为了解决这些问题。
作用:JS代码风格检查器,能将违反规则的代码修复。
Webpack 下,可以使用
eslint-webpack-plugin
接入 ESLint 工具,步骤:
# 安装 webpack 依赖
yarn add -D webpack webpack-cli
# 安装 eslint
yarn add -D eslint eslint-webpack-plugin
# 简单起见,这里直接使用 standard 规范
yarn add -D eslint-config-standard eslint-plugin-promise eslint-plugin-import eslint-plugin-node
eslintrc
配置文件,内容:// .eslintrc
{
"extends": "standard"
}
webpack.config.js
配置文件,补充 eslint-webpack-plugin
配置:// webpack.config.js
const path = require('path')
const ESLintPlugin = require('eslint-webpack-plugin')
module.exports = {
entry: './src/index',
mode: 'development',
devtool: false,
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
// 添加 eslint-webpack-plugin 插件实例
plugins: [new ESLintPlugin()]
}
npx webpack
也可以使用第三方扩展来进行特殊的代码风格检测
eslint-config-airbnb
:Airbnb 提供的代码风格规则集,算得上 ESLint 生态第一个成名的规则集合eslint-config-standard
:Standard.js 代码风格规则集,史上最便捷的统一代码风格的方式eslint-plugin-vue
:实现对 Vue SFC 文件的代码风格检查eslint-plugin-react
:实现对 React 代码风格检查@typescript-eslint/eslint-plugin
:实现对 TypeScript 代码风格检查eslint-plugin-sonarjs
:基于 Sonar 的代码质量检查工具,提供圈复杂度、代码重复率等检测功能本文主要记录了Webpack配置底层逻辑结构以及如何借助Babel、TS、ESLint构建JS环境