webpack核心概念
Entry
入口,指定webpack入口文件,从该文件开始打包;
Output
输出,打包文件输出名称及路径
Loader
支持webpack处理非js文件
Plugins
插件,支持webpack执行范围更广的任务,包括打包优化、压缩、定义变量等;
Module
配置webpack打包模式
webpack安装模块:
yarn add webpack webpack-cli html-webpack-plugin webpack-dev-server css-loader style-loader less-loader mini-css-extract-plugin css-minimizer-webpack-plugin csv-loader xml-loader yaml toml
工具安装后需手工在项目根目录下创建配置文件:webpack.config.js
可根据生产及开发环境生成对应配置文件:
- 开发环境:
webpack.config.dev.js
,保留entry、output、module、mode、plugins、devtool、devServer - 生产环境:
webpack.config.prod.js
,保留entry、output, module ,mode,plugins,optimization
可通过提取公共配置降低重复工作:
// 通用配置提取到webpack.config.common.js,格式与webpack.config.js保持一致
// 全局安装webpack-merge插件进行合并
const {merge} = require('webpack-merge')
const commonConfig = require('./webpack.config.common.js')
const devConfig = require('./webpack.config.dev.js')
const prodConfig = require('./webpack.config.prod.js')
module.exports = (env) => {
switch (true) {
case env.development === "development":
return merge(commonConfig, devConfig);
case env.production === "production":
return merge(commonConfig, prodConfig);
default:
return new Error("No matching configuration was found");
}
}
npx webpack -c webpack.config.dev.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssextractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')
const webpack = require('webpack')
const yaml = require('yaml')
module.exports = (env) => {
return {
entry: {
// 方案一,单入口模式
// index: './src/main.js', // 指定源码入口文件名 // 多入口模式 /* index: { import: './src/index.js', dependOn: 'shared', }, another: { import: './src/other.js', dependOn: 'shared', }, // 其他入口文件名 shared: 'lodash', // 指定多入口共享模块打包至shared.js文件中 */
// 方案三, 使用webpack插件 抽离公共模块 配置在optimize中
index: './src/main.js',
another: './src/other.js',
},
output: {
filename: '[name].[contenthash].js', // 指定打包文件名,浏览器缓存时会根据文件名判断是否变更,建议使用名称加contenthash方式生成文件名
path: path.resolve(__dirname, './dist'), // 指定打包路径
clean: true, // 自动清空打包目录
assetModuleFilename: 'images/[contenthash][ext]',
publicPath: 'http://localhsot:8080/', // 指定打包后引用资源路径前缀
pathinfo: false, // 编译代码中不包含路径信息
},
// 可选为 none, development及 production
mode: env.production ? 'production' : 'development',
resolve: {
// 配置路径别名
alias: {
'@': path.resolve(__dirname, './src'),
},
// 按顺序默认识别扩展名
extensions: ['.js', '.vue', '.json'],
},
externalsType: 'script', // 指定cdn模块以什么方式暴露
// 指定CDN模块,不会进行打包
externals: {
jquery: ['https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js', 'jQuery'],
},
plugins: [
// 指定使用插件打包文件
new HtmlWebpackPlugin({
template: './index.html', // 使用源文件作为模板
filename: 'app.html', // 打包后文件名
inject: 'body', // js插入标签路径
}),
new MiniCssextractPlugin({
filename: 'style/[contenthash][.ext]', // 配置css抽离生成的文件路径及文件名
}),
// 配置全局变量
new webpack.ProgressPlugin({
_: 'axios',
}),
],
module: {
rules: [
// 全局导出
{
test: require.resolve('./src/main.js'),
use: 'exports-loader?type=commonjs&exports=file,multiple|helpers.parse|parse',
},
{
test: /\.png$/, // 打包png后缀文件
type: 'asset/resource', // 作为资源打包至assets目录
generator: {
filename: './dist/images/[contenthash][ext]', // 优先 指定打包文件路径、文件名及后缀名
},
},
{
test: /\.svg$/, // 打包svg扩展名文件
type: 'asset/inline', // 将资源文件打包成base64信息至代码文件中
},
{
test: /\.txt$/, // 打包txt扩展名文件
type: 'asset/source', // 将资源文件直接打包至代码文件中
},
{
test: /\.jpg$/, // 打包jpgt扩展名文件
type: 'asset', // 通用资源类型,自动选择创建为resource或inline,根据资源大小自动选择,默认为8k以下inline
// 自定义临界值 parser: {
dataUrlCondition: {
maxSize: 4 * 1024 * 1024, // 临界值修改为4Mb
},
},
},
{
test: /\.(css|less)$/,
use: ['style-loader', 'css-loader', 'less-loader'], // 使用指定loader对对应资源进行解析并打包
},
{
test: /\.(css|less)$/,
use: [MiniCssextractPlugin.loader, 'css-loader', 'less-loader'], // 将所有样式文件抽离合并为一个样式文件,并超链接至代码文件中
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
type: 'asset/resource', // resource支持加载任意类型资源
},
{
test: /\.(tsv|csv)$/,
use: 'csv-loader', // 使用loader加载csv/tsv数据,转换为数组
},
{
test: /\.xml$/,
use: 'xml-loader', // 使用loader加载xml数据
},
{
test: /\.yaml$/, // 自定义json模块的parser
type: 'json',
parser: {
parse: yaml.parse,
},
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules文件下下js文件加载
use: {
loader: 'babel-loader', // 指定loader加载js
option: {
presets: ['@babel/preset-env'], // 使用指定插件集合加载js
plugins: [['@babel/plugin-transform-runtime']], // 兼容 async/await语法
},
},
},
// 配置webpack集成eslint语法规范
{
test: /\.(js|vue)$/,
use: ['babel-loader', 'eslint-loader'],
},
],
},
optimization: {
minimizer: [
new CssMinimizerPlugin(), // 需配合mode:production 压缩加载的CSS文件
new TerserPlugin(), // 启用打包代码压缩
],
// 配合entry 方案三使用
splitChunks: {
// chunks: 'all',
cacheGroups: {
test: /[\\/]node_modules[\\/]/, // 以固定名称缓存第三方模块
name: 'vendors',
chunks: 'all',
},
},
usedExports: true, // 启用treeshaking
},
// 启用source-map,可直接查看源文件报错位置
devtool: 'inline-source-map',
devServer: {
static: './dist',
compress: true, // 启动压缩
port: 3000, // 指定服务启动端口
headers: {
'X-Access-Token': 'abc123', // 添加token到响应头
},
proxy: {
'/api': 'http://localhost:9000', // 解决跨域访问问题
},
http2: true, // 启用https 或者直接使用https:true 需自行配置证书
historyApiFallback: true, // 解决spa路由刷新可能报错
host: '0.0.0.0', // 允许局域网访问
hot: true, // 开启模块热替换 HMR
liveReload: true, // 开启模块热加载
// 禁止devServer页面eslint错误提示覆盖层 client: {
overlay: false,
},
},
}
}
npx webpack 自动寻找项目内webpack命令路径并执行
npx webpack –watch 自动检测文件变化并重新打包
npx webpack-dev-server –open 启动dev-server
babel-loader
babel-loader用于将js代码加载为向下兼容模式
安装插件
yarn add babel-loader @babel/core @babel/preset-env @babel/runtime @babel/plugin-transform-runtime terser-webpack-plugin -D
- babel-loader: 在webpack中应用babel解析ES6的桥梁
- @babel/core:babel核心代码
- @babel/preset-env:babel预设,一组babel插件的集合
- @babel/runtime:兼容async/await语法
- @babel/plugin-transform-runtime:按需调用runtime
regeneratorRuntime: 是webpack打包生成的全局辅助函数,由babel生成,用于兼容async/await语法
webpack好处
代码分离,提升加载速度
分离方法:
- 入口手动分离
- 动态加载
- 懒加载
- 预获取/预加载
- prefetch: 预获取,在页面加载完成后,利用空闲资源进行文件加载
- preload:预加载,
//在需要代码分离引入的模块前添加注解,可指定代码分离后文件名
import(/*webpackChunkName: 'math', webpackPrefetch: true*/ './utils/abc.js')
package.json
该配置文件可通过npm init
自动生成,该文件结构为:
{
"name": "frontend",
"version": "0.1.0",
"private": true,
// 定义npm run xxx脚本命令
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
// 业务依赖模块
"dependencies": {
"axios": "^0.24.0",
"bcryptjs": "^2.4.3",
"core-js": "^3.6.5",
"dateformat": "^5.0.2",
"element-ui": "^2.15.6",
"jsonwebtoken": "^8.5.1",
"vue": "^2.6.11",
"vue-clipboard2": "^0.3.3",
"vue-router": "^3.5.3",
"xlsx": "^0.17.4"
},
// 开发依赖模块
"devDependencies": {
"@babel/core": "^7.16.7",
"@babel/plugin-transform-runtime": "^7.16.7",
"@babel/preset-env": "^7.16.7",
"@babel/runtime": "^7.16.7",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.2.3",
"babel-plugin-component": "^1.1.1",
"compression-webpack-plugin": "5.0.1",
"css-loader": "^6.5.1",
"css-minimizer-webpack-plugin": "^3.3.1",
"csv-loader": "^3.0.3",
"eslint": "7.30.0",
"eslint-config-prettier": "^8.3.0",
"eslint-config-standard": "^16.0.3",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-standard": "^5.0.0",
"eslint-plugin-vue": "^6.2.2",
"html-webpack-plugin": "^5.5.0",
"less": "^4.1.2",
"less-loader": "7.3.0",
"mini-css-extract-plugin": "^2.4.6",
"prettier": "^2.5.1",
"style-loader": "^3.3.1",
"terser-webpack-plugin": "^5.3.0",
"toml": "^3.0.0",
"vue-style-loader": "^4.1.3",
"vue-template-compiler": "^2.6.11",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.7.2",
"xml-loader": "^1.2.1",
"yaml": "^1.10.2"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
eslint
语法规范工具
{
// 配置支持运行环境
"env": {
"browser": true, // 支持浏览器
"es2021": true // 支持es2021
},
"extends": ["airbnb-base"], // 使用规则标准
"parserOptions": {
"ecmaVersion": 12, //ecma版本
"sourceType": "module" //检查类型
},
// 配置自定义校验规则
"rules": {
}
// 配置全局变量
"globals": {
}
}
eslint集成webpack
插件依赖
yarn add webpack webpack-cli webpack-dev-server html-webpack-plugin babel-loader eslint-loader @babel/core -D
webpack.config.js配置
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader', 'eslint-loader']
}
]
}
githooks & husky
git在仓库根目录下存在一个.git 隐藏文件,其子目录hooks内提供了一系列样例文件,以.sample结尾,对其重命名,去掉.sample后缀名则生效,文件名不能修改;
例如: pre-commit.sample为提交前运行钩子,去除后缀名后生效,作为用执行git commit前自动执行其内命令;
自定义githooks路径 : git config core.hooksPath xxx
husky
模块安装
yarn add huskey -D
npx husky install # 在项目下创建一个隐藏文件夹 .husky
# 创建钩子
npx husky add .husky/pre-commit 'XXX'
模块
import a from './a' // ES6语法
const a = require('./a') // commonJs语法
模块解析
tree shaking
在webback.config.js中优化配置项中启用
sideEffects
sideEffects在package.json文件中
指定哪些文件是具有副作用的,tree shaking不应该删除
sideEffects: ['.global.css'] //指定不删除global.css结尾的文件
[[Webpack项目打包配置案例]]
[[Rollup打包工具]]
[[ESLINT与PRETTIER]]