webpack 最全配置


const path = require('path')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); // 压缩css
const TerserPlugin = require('terser-webpack-plugin') // 压缩js
/*
代码分割有三种方法:
1 入口起点:使用 entry 配置手动地分离代码。
2 防止重复:使用 Entry dependencies 或者 SplitChunksPlugin 去重和分离chunk。
3 动态导入:通过模块的内联函数 import 调用来分离代码。
*/
/*
postcss-loader
npm i --save-dev autoprefixer
npm i -D postcss-nested
npm install -D style-loader css-loader postcss-loader postcss
可以使用 autoprefixer 插件为CSS 规则添加前缀
npm i --save-dev autoprefixer
可以使用 postcss-nested 插件为CSS提供编写嵌套的样式语法支持
npm i -D postcss-nested
postcss-loader 需要根据 browserslist 获取兼容范围,所以需要在package.json 中标明:
"browserslist": [ // 更多的 browserslist 请参阅https://github.com/browserslist/browserslist#readme
"> 1%", // 支持在全球使用率超过1%的浏览器
"last 2 versions" // 每个浏览器中最新的两个版本,注意 versions,带s
]
*/
/*
集成 typescript
npm i typescript -S
npm i ts-loader -D
在项目根目录下添加一个ts的配置文件——tsconfig.json,我们可以用ts自带的工具来自动化生成它。
npx tsc --init
生成配置文件后,保留这些
{
"compilerOptions": {
"outDir": "./dist/",
"noImplicitAny": true,
"sourceMap": true,
"module": "es6",
"target": "es5",
"jsx": "react",
"allowJs": true,
"moduleResolution": "node"
}
}
*/
module.exports = {
entry: {
index: {
import: './src/index.js', // 启动时需加载的模块
dependOn: 'common_chunk', // 当前入口所依赖的入口
},
another: {
import: './src/another_module.js',
dependOn: 'common_chunk', // 当前入口所依赖的入口
},
common_chunk: 'lodash' // 当上面两个模块有lodash这个模块时,就提取出来并命名为shared chunk
},
output: {
// 将 js 文件放到一个文件夹中
filename: 'js/bundle_[name]_[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true, // 在生成文件之前清空 output 目录
assetModuleFilename: 'images/[hash][ext][query]' // 这里
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
optimization: {
minimizer: [
// 这将仅在mode: production 生产环境开启 CSS 优化
// 如果还想在开发环境下启用 CSS 优化,optimization.minimize 设置为 true: minimize: true,
new CssMinimizerPlugin(),
new TerserPlugin()
],
splitChunks: {
chunks: "all",
cacheGroups: {
// layouts通常是admin项目的主体布局组件,所有路由组件都要使用的
// 可以单独打包,从而复用
// 如果项目中没有,请删除
layouts: {
name: "layouts",
test: path.resolve(__dirname, "../src/layouts"),
priority: 40,
},
// 如果项目中使用element-plus,此时将所有node_modules打包在一起,那么打包输出文件会比较大。
// 所以我们将node_modules中比较大的模块单独打包,从而并行加载速度更好
// 如果项目中没有,请删除
elementUI: {
name: "chunk-elementPlus",
test: /[\\/]node_modules[\\/]_?element-plus(.*)/,
priority: 30,
},
// 将vue相关的库单独打包,减少node_modules的chunk体积。
vue: {
name: "vue",
test: /[\\/]node_modules[\\/]vue(.*)[\\/]/,
chunks: "initial",
priority: 20,
},
libs: {
name: "chunk-libs",
test: /[\\/]node_modules[\\/]/,
priority: 10, // 权重最低,优先考虑前面内容
chunks: "initial",
},
}
}
},
plugins: [
new MiniCssExtractPlugin({filename: 'styles/[hash].css'})
],
module: {
rules: [
/*
useBuiltIns
参数有 “entry”、“usage”、false 三个值
默认值是 false ,此参数决定了babel打包时如何处理 @babel/polyfill 语句。
“entry”: 会将文件中 import '@babel/polyfill' 语句 结合 targets ,转换为一系列引入语句,去掉目标浏览器已支持的 polyfill 模块,不管代码里有没有用到,只要目标浏览器不支持都会引入对应的 polyfill 模块。
“usage”: 不需要手动在代码里写 import '@babel/polyfill' ,打包时会自动根据实际代码的使用情况,结合 targets 引入代码里实际用到部分 polyfill 模块
false: 对 import '@babel/polyfill' 不作任何处理,也不会自动引入 polyfill 模块。需要注意的是在 webpack 打包文件配置的 entry 中引入的 @babel/polyfill 不会根据 useBuiltIns 配置任何转换处理。
由于 @babel/polyfill 在7.4.0中被弃用,我们建议直接添加corejs并通过corejs选项设置版本
npm i core-js@3 -S
npm i babel-loader @babel/core @babel/preset-env -D
npm install --save @babel/runtime
npm install -D @babel/plugin-transform-runtime
*/
{
test: /\.ts$/,
use: [
{
loader: 'babel-loader',
options: {
plugins: ['@babel/plugin-transform-runtime'],
presets: [
[
'@babel/preset-env',
{
// 项目所支持的浏览器的配置
targets: [ // 告诉@babel/preset-env遇到了这样的浏览器需要通过Polyfills使用添加垫片
'> 1%', // 支持市场份额超过 1% 的浏览器
'last 2 version', // 支持每一个浏览器最后两个版本
'safari >= 7', // 大于等于7版本的 safari
],
useBuiltIns: 'usage',
corejs: 3, // 添加corejs配置
},
],
],
},
},
{ loader: 'ts-loader'},
{ loader: 'eslint-loader' },
],
exclude: /node_modules/,
},
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
plugins: ['@babel/plugin-transform-runtime'],
presets: [
[
'@babel/preset-env',
{
// 项目所支持的浏览器的配置
targets: [ // 告诉@babel/preset-env遇到了这样的浏览器需要通过Polyfills使用添加垫片
'> 1%', // 支持市场份额超过 1% 的浏览器
'last 2 version', // 支持每一个浏览器最后两个版本
'safari >= 7', // 大于等于7版本的 safari
],
useBuiltIns: 'usage',
corejs: 3, // 添加corejs配置
},
],
],
},
},
{
loader: 'eslint-loader',
},
]
},
{
test: /\.css$/i,
use: [
MiniCssExtractPlugin.loader, 'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: { // 也可使用 PostCSS 配置文件 postcss.config.js 代替
plugins: [
require('autoprefixer'), // 为CSS 规则添加前缀
require('postcss-nested'), // 为CSS提供编写嵌套的样式语法
],
},
},
},
],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
parser: {
// 如果不设置 maxSize,
// webpack 将按照默认条件,自动地在 resource 和 inline 之间进行选择:小于 8kb 的文件
dataUrlCondition: {
maxSize: 4 * 1024 // 4kb
}
}
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name]_[hash][ext]'
}
},
// asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。
// asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。
// asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。
// asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源体积限制实现。
/*
自定义输出文件名
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
assetModuleFilename: 'images/[hash][ext][query]' // 这里
},
*/
],
},
}
/*
dev 和 prod config 配置文件的区别:
output: {
filename: 'js/[name].[contenthash].js', // 出口文件名
},
output: {
filename: 'js/[name].js', // 出口文件名
},
devtool: 'inline-source-map', // dev
devServer mode
optimization: {
minimize: true, // 开发环境下启用 CSS 优化
},
optimization: {
minimizer: [
new CssMinimizerPlugin(), // css 压缩
new TerserPlugin() // js 压缩
],
},
合并配置文件
const { merge } = require('webpack-merge')
const commonConfig = require('./webpack.config.common.js')
const productionConfig = require('./webpack.config.prod.js')
const developmentConfig = require('./webpack.config.dev.js')
module.exports = (env) =>{
switch (true)
case env.development:
return merge(commonConfig, developmentConfig)
case env.production:
return merge(commonConfig, productionConfig)
default:
throw new Error('No matching configuration was found!');
}
}
修改package.json npm脚本
{
"scripts": {
"start": "webpack serve -c ./config/webpack.config.js --env development",
"build": "webpack -c ./config/webpack.config.js --env production"
},
}
*/