欢迎光临散文网 会员登陆 & 注册

webpack 最全配置

2023-11-17 18:22 作者:不良人王德发  | 我要投稿


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"
   },
 }

*/


webpack 最全配置的评论 (共 条)

分享到微博请遵守国家法律