zoukankan      html  css  js  c++  java
  • webpack配置整理


    最近在学习webpack,整理一下代码

    主文件webpack.config.js

    // resolve用来拼接绝对路径的方法
    const { resolve } = require('path');
    const htmlWebpackPlugin = require('html-webpack-plugin');
    const miniCssExtractPlugin = require('mini-css-extract-plugin');
    const optimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
    const addAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
    // Happypack任务分解为多个子进程,完成后并入主线程(适合大型项目)
    const HappyPack = require('happypack');
    // 根据cpu数量创建线程池
    const happyThreadPool = HappyPack.ThreadPool({size:OscillatorNode.cpus().length});
    /*
    PWA:渐进式网络开发应用程序(离线可访问)
    workbox --> workbox-webpack-plugin
     */
    const workBoxWebpackPlugin = require('workbox-webpack-plugin');
    // 以前使用的是Ulgify,现在webpack内置terser plugin进行文件压缩优化
    const TerserPlugin = require('terser-webpack-plugin');
    const webpack = require('webpack');
    /*
    tree shaking:去除无用代码
    前提:1.必须使用es6模块化 2.开启production模块
    作用:减少代码体积
    "sideEffects": false 所有代码都没有副作用(都可以进行tree shaking)
    问题:可能会把除了js文件之外的文件也去除掉可以通过"sideEffects": ["*.css"]不进行tree shaking
     */
    const commonCssLoader = [
      // use数组中loader顺序:从后到前的顺序,依次执行
      // 创建style标签,将js中的样式资源插入进行,添加到head中生效
      // 'style-loader',
      // 取代style-loader 作用:提取js中的css成单独文件
      miniCssExtractPlugin.loader,
      // 将css文件变成commonjs模块加载到js中,里面内容是样式字符串
      'css-loader',
      /*
       css 兼容性处理:postcss --> postcss-loader postcss-preset-env
       */
      // 使用loader的默认配置
      // postcss-loader 修改loader的配置
      {
        loader: 'postcss-loader',
        options: {
          ident: 'postcss',
          plugins: () => [
            // postcss的插件
            require('postcss-preset-env')()
          ]
        }
      }];
    process.env.NODE_ENV = 'development';
    module.exports = {
      // import导入的没有加后缀的文件,自动加上后缀
      resolve: {
        extensions: ['.js']
      },
      // webpack配置
      // 入口起点
      entry: ['./index.js', './demo.html'],
      output: {
        // 输出文件名
        filename: 'js/built.js',
        // 输出路径
        path: resolve(__dirname, 'build')
      },
    // loader的配置
      module: {
        // 不打包的文件
        noParse: /node_modules/(echarts)/,
        // 详细loader配置
        rules: [
          // 1.js兼容性处理:babel-loader @babel/preset-env @babel/core
          // 问题:babel只能转换一些基本语法 例如:Promise就不能转换
          // 2. 全部js兼容性处理 --> @babel/polyfill
          // 解决了所有的兼容性问题,但是打包后的文件体积过大
          // 3.需要做兼容性处理的才进行改良:按需加载 --> core.js
          {
            test: /.js$/,
            exclude: /node_modules/,
            use: [
              // 开启多进程打包
              // 进程启动大概为600ms,进程通信也有开销
              // 只有工作消耗时间比较长,才需要多进程打包
              'thread-loader',
              {
                loader: 'babel-loader',
                options: {
                  // 预设:指示babel做怎样的兼容性处理
                  presets: [
                    ['@babel/preset-env',
                      {
                        // 按需加载
                        useBuiltIns: 'usage',
                        // // 指定core-js版本
                        corejs: {
                          version: 3
                        },
                        // 指定兼容性做到哪个版本的浏览器
                        targets: {
                          chrome: '60',
                          firefox: '60',
                          ie: '9',
                          safari: '10',
                          edge: '17'
                        }
                      }]
                  ],
                  // 开启babel缓存
                  // 第二次构建,会读取之前的缓存
                  cacheDirectory: true,
                  /*
                  文件资源缓存
                  hash:每次webpack构建时会生成一个唯一的hash值。
                  问题:因为js和css同时使用一个hash值
                  如果重新打包,会导致所有缓存失效。(可能我却只改动一个文件)
                  chunkhash:根据chunk生成的hash值。如果打包来源于同一个chunk,那么hash值就一样
                  因为css是在js中被引入的,所以同属于一个chunk
                  contenthash:根据文件的内容生成hash值,不同文件hash值一定不一样 --> 让代码上线运行缓存更好使用
                   */
                }
              }
            ]
          },
          // 语法检查:eslint-loader eslint
          // 只检查自己写的源代码,不检查第三方库的代码
          // 设置检查规则: package.json中eslintConfig中设置~
          // 推荐airbnb规则 --> eslint-config-airbnb-base eslint eslint-plugin-import
          {
            test: /.js$/,
            exclude: /node_modules/,
            loader: 'eslint-loader',
            enforce: 'pre',
            options: {
              // 自动修复语法
              fix: true
            }
          },
          {
            // 以下loader只会执行一个
            // 如果有两个loader同时处理一种类型文件,则会出错
            oneOf: [
              {
                test: /.css$/,
                use: [...commonCssLoader]
              },
              {
                // 匹配哪些文件
                test: /.less$/,
                // 使用哪些loader进行处理
                use: [
                  ...commonCssLoader,
                  'less-loader'
                ]
              },
              {
                test: /.(jpg|png|gif)$/,
                // 需要下载两个loader,下载url-loader以及它依赖的file-loader
                loader: 'url-loader',
                options: {
                  // 图片小于8kb,就会被base64处理
                  // 优点:减少请求数量(减轻服务器压力)
                  // 缺点:图片体积会更大(文件请求速度更慢)
                  limit: 8 * 1024,
                  esModule: false,
                  outputPath: 'images',
                  name: '[hash:10].[ext]'
                }
              },
              {
                test: /.html$/,
                // 处理html文件的img图片(负责引入img,从而能被url-loader进行处理)
                loader: 'html-loader'
              },
              // 打包其他资源(除了html/js/css资源以外的资源)
              {
                exclude: /.(js|css|html|less|jpg|png|gif)$/,
                loader: 'file-loader',
                options: {
                  outputPath: 'media',
                  name: '[hash:10].[ext]'
                }
              }
            ]
          }
        ]
      },
      // externals: {
      //   // 忽略库名 -- npm包名,设置之后的库不参与打包
      //   jquery: 'jQuery'
      // },
      // plugins的配置
      plugins: [
        // 详细plugins的配置
        // html-webpack-plugin
        // 功能:默认会创建一个空的html,自动引入打包输出的所有资源(JS/CSS)
        // 需求:需要有结构的HTML文件
        new htmlWebpackPlugin({
          template: './demo.html',
          minify: {
            // 移除空格
            collapseWhitespace: true,
            // 移除注释
            removeComments: true
          }
        }),
        new CleanWebpackPlugin(),
        new miniCssExtractPlugin({
          filename: 'css/built.css'
        }),
        // 压缩CSS
        new optimizeCssAssetsWebpackPlugin(),
        new workBoxWebpackPlugin.GenerateSW({
          /*
          1.帮助serviceworker快速启动
          2.删除旧的serviceworker
          生成一个serviceworker配置
           */
           clientsClaim:true,
          skipWaiting: true
        }),
        new webpack.HotModuleReplacementPlugin(),
        // 告诉webpack那些库不参与打包,同时使用时的名称也得变~
        new webpack.DllReferencePlugin({
          manifest: resolve(__dirname, 'dll/manifest.json')
        }),
        new BundleAnalyzerPlugin(),
        new HappyPack({
          id: 'babel',
          threads: happyThreadPool,
          // happypack有很多不支持的loader,请查看官方进行使用
          loaders: ['babel-loader']
        })
        // 将某个文件打包输出去,并在html中自动引入该资源
        // new addAssetHtmlWebpackPlugin({
        //   filepath: resolve(__dirname, 'dll/jquery.js')
        // })
      ],
      // 模式
      mode: 'production', // 开发模式
      /*
      可以将node_modules中代码单独的打包一个chunk最终输出
      自动分析多入口chunk中,有没有公共的文件,如果有会打包成单独一个chunk
       */
      optimization: {
        splitChunks: {
          chunks: 'all'
        },
        minimizer: [
           new TerserPlugin({
             // 加快构建速度
             cache: true,
             // 开启多线程
             // parallel: true,
             terserOptions: {
               // 打包时将无用代码去除
               compress: {
                 unused: true,
                 drop_debugger: true,
                 drop_console: true,
                 dead_code: true
               }
             }
           })
        ]
      },
      // 开发服务器 devServer:用来自动化(自动编译,自动打开浏览器,自动刷新浏览器...)
      // 特点:只会在内存中编译打包,不会有任何输出
      // 启动devServer指令为:npx webpack-dev-server
      devServer: {
        contentBase: resolve(__dirname, 'build'),
        /*
        HMR:hot module replacement 热模块替换/模块热替换
        作用:一个模块发生变化,只会重新打包一个模块(而不是打包所有模块)
        极大提升构建速度
    
        样式文件:可以使用HMR功能,但是需要使用style-loader,style-loader内部实现了HMR
        js文件:默认不能使用HMR功能 -> 需要修改js代码,添加支持HMR功能的代码
        注意:HMR功能对js的处理,只能处理非入口js文件的其他文件
        html文件:默认不能使用HMR功能,同时会导致问题,html文件不能热更新,解决:修改entry入口,将html文件引入
         */
        hot: true,
        hotOnly: true,
        // 启动gzip压缩
        compress: true,
        // 端口号
        port: 3000
      },
      devtool: 'source-map'
    };
    /*
    source-map:一种 提供源代码到构建后代码映射 技术(如果构建后代码出错了,通过映射可以追踪源代码错误)
    [inline-[hidden-[eval-][nosources-][cheap-[module-]]source-map
    
    inline-source-map:内联(只生成一个sourceMap)
    hidden-source-map:外部
    eval-source-map:内联(每个文件生成一个sourceMap)
    nosources-source-map:外部
    cheap-source-map:外部
    cheap-module-source-map: 外部
     */
    /* package.json添加配置
    "browerslist": {
        "development": [
          "last 1 chrome version", // 最近的一个版本
          "last 1 firefox version",
          "last 1 safari version"
        ],
        "production": [
          ">0.2%", // 全球有0.2%的用户使用的浏览器(也就是兼容的浏览器很老)
          "not dead", // 
          "not op_mini all" // 不兼容op_mini
        ]
      },
      "eslintConfig": {
        "extends": "airbnb-base", // 遵从airbnb代码风格
        "env": {
          "browser": true, // 浏览器环境
          "es6": true
        }
      },
      "sideEffects": false // 启动tree shaking
    */
    

    dll文件

    /*
     使用dll技术,对某些库(第三方库:jquery,react,vue...)进行单独打包
     当你运行webpack时,默认查找webpack.config.js配置文件
     需求:需要运行webpack.dll.js文件
     webpack --config webpack.dll.js
     */
    const { resolve } = require('path');
    const webpack = require('webpack');
    module.exports = {
      entry: {
        // 最终打包生成的[name] ==> jquery
        // ['jquery'] --> 要打包的库是jquery
        jquery: ['jquery']
      },
      output: {
        filename: '[name].js',
        path: resolve(__dirname, 'dll'),
        library: '[name]_[hash]' // 打包的库里面向外暴露出去的内容叫什么名字
      },
      plugins: [
        // 打包生成一个 manifest.json --> 提供和jquery映射
        new webpack.DllPlugin({
          name: '[name]_[hash]', // 映射库的暴露的内容名称
          path: resolve(__dirname, 'dll/manifest.json') // 输出文件路径
        })
      ],
      mode: 'production'
    };
    
  • 相关阅读:
    mysql外键和连表操作
    数据库的操作
    进程之select和epoll
    jwt的应用生成token,redis做储存
    为什么前后端分离不利于seo
    redis的bitmap
    lnmp环境的nginx的tp5配置
    虚拟机安装cenos7后ifcfg看网卡无inet地址掩码等信息
    rsa加密
    hydra命令
  • 原文地址:https://www.cnblogs.com/smallZoro/p/12722174.html
Copyright © 2011-2022 走看看