• webpack性能优化配置


    webpack性能优化

    • 开发环境性能优化
    • 生产环境性能优化

    开发环境性能优化

    • 优化打包构建速度
      // 在webpack.config.js中配置  hot : true
      devServer : {
          contentBase : path.resolve(__dirname,"build"),
          compress : true,
          port : 3000,
          open : true,
          //开启HMR热模块替换
          hot : true,
      }  
      /**
       * HMR : hot moudle replacement  热模块替换/模块热替换
       * 作用:一个模块发生改变,只会重新打包当前一个模块,不会影响其他模块,极大提高打包速度
       * 
       *
       *样式文件:可以使用HMR功能,因为style-loader内部已经做了功能实现
       *
       *
       *js文件 : 默认情况下js文件是不能使用HMR功能的
       *  注意:HMR功能对js的处理只能处理非入口js的其他文件。(依赖都在入口文件引入)
       *  在入口文件做一下逻辑
          ```js
      
              if(module.hot){
                  //当module.hot为true 说明开启了HMR功能,
                  module.hot.accept('xxxxx.js',function(){
                      // module.hot.accept 监听xxxxx.js 文件的变化,不会影响其他文件的打包构建。
                      执行方法
                  })
              }
      
          ```js
       * 
       *
       *html文件:默认情况下htm;文件是不能使用HMR功能的,同时会导致html不能热更新,(不建议做HMR)
       *  解决方案: 修改entry入口 将html文件引入
      */
      
    • 优化代码调试
          //在webpack.config.js中
          devtool : 'source-map',
      
          /*
              source-map 提供源代码到构建后代码 映射
               通俗解释:如果构建后代码报错,通过映射可以追踪到源代码报错地方。
          */
      
          /*
              devtool后面参数汇总:
      
                  source-map : 外部
                      错误代码准确信息 和 源代码的准确位置
      
                  inline-source-map : 内联
                      只会生成一个内联 source-map
                      错误代码准确信息 和 源代码的准确位置
      
                  hidden-source-map : 外部
                      错误代码的原因  但是 不会追踪到源代码的错误的位置
      
                  eval-source-map : 内联
                      每一个文件都生成对应的source-map  都在eval
                      错误代码准确信息 和 源代码的准确位置  文件会多了一个hash值
      
                  nosoureces-source-map : 外部
                      错误代码准确信息  但是  没有源代码信息
      
                  cheap-source-map : 外部
                      错误代码准确信息 和 源代码的准确位置  但是 整行都会报错,不会具体的那一段代码
      
                  cheap-module-source-map : 外部
                      错误代码准确信息 和 源代码的准确位置 
      
                  内联  和   外部的区别 : 
                      a: 外部生成了文件,内联没有生成文件
                      b: 内联构建速度更快
      
      
              怎么使用source-map:
                  开发环境:
                      速度快,调试更加方便友好,
                          速度:
                              eval > inline > cheao > ...
                              可以组合应用:
                              eval-cheap-source-map
                              eval-source-map
                          调试:
                              source-map
                              cheap-module-source-map
                              cheap-source-map
      
                  比较好----->  eval-source-map / eval-cheap-module-source-map
      
                  生产环境:
                      源代码要不要隐藏?调试要不要友好
                      内联会让代码体积变大,所有在生产环境尽量不要使用内联
                       nosoureces-source-map   全部隐藏
                       hidden-source-map   只隐藏源代码,会提示构建后代码错误信息
      
                  比较好----->  source-map   /  cheap-module-source-map 
                  
          */
      

    生产环境性能优化

    • 优化打包构建速度

    • 优化代码运行性能

      • oneOf优化

            moudle : {
                rules : [
                    {
                        //以下loader只会匹配以下
                        //执行逻辑:匹配成功之后就不会再往下匹配
                        //注意不能有两个配置处理同一种类型文件
                        //如果有两个配置处理一个文件(例如:js eslint babel ) 可以把优先执行的配置单独拎出来,{ } 放在rules里面。
                        onnOf : [
                            {...配置}
                        ]
                    }
                ]
            }
        
      • 缓存

            //对bable缓存
            {
                test: /.js$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                //开启缓存
                cacheDirectory : true
            }
        
        
            //文件资源缓存:
                /*
                    filename : 'css/built.[hash:10].css'
                    hash : 每次webpack构建时会生成一个唯一的hash值
                        问题:因为js和css同时使用一个hash值
                            如果重新打包会导致所有缓存失败,
        
        
                    filename : 'css/built.[chunkhash:10].css'
                    chunkhash : 根据chunk 生成的hash值,如果打包来源于同一个chunk  那么hash值就一样
                        问题:因为js和css同时使用一个hash值
        
        
                    filename : 'css/built.[contenthash:10].css'
                    contenthash : 根据文件内容生成的hash值,不同文件hash值不一样
                    
                */
        
      • tree shaking 去除无用的代码

            //当webpack.config.js mode:'production' 则开启 tree shaking
            /*
                前提条件:
                    a: 必须使用es6模块化
                    b: 开启production环境
                    
                作用:减少代码体积
        
                在package.json中配置
                    "sideEffects" : false,
                    所有代码没有副作用(都可以进行 tree shaking)
        
                    问题:可能会把css/ @babel/polyfill 文件干掉
                    "sideEffects" : ["*.css","*.scss"],
        
            */
            
        
      • code split ( 代码分割 )

            //单入口、多入口
            module.exports = {
                //entry : './src/main.js' // 单入口
                //多入口 
                entry : {
                    main : './src/main.js',
                    test : './src/test.js'
                },
        
                //输出配置
                output : {
                    //name 给输出的文件命名,否则多入口输出都是一个文件名称。
                    filename : js[name].js,
                    path : path.resolve(__dirname,'build')
                }
            }
        
            //webpack.config.js
            //将node_module中代码单独打包一个chunk输出
            //会分析多入口chunk中,有没有公共的文件。如果有只打包一个
             //例如 a.js  b.js都依赖jquery  这样单独拎出jquery打包
            module.exports = {
                optimization:{
                    splitChunks : {
                        chunks : 'all'
                    }
                }
            }
        
            //通过js逻辑,完成文件被单独打包一个chunk
            import(/*webpacjChunkName:test*/'.test')
                .then(() => {
                    console.log('文件加载成功')
                })
                .catch(() => {
                    console.log('文件加载失败')
                })
        
      • 懒加载 预加载

            //懒加载
            //场景:当点击按钮的时候在调用某个模块、以及某个模块中的方法
            //不直接 import引入 而是把引入放在逻辑里面
            btn.addEventListener('click',() => {
                import(/*webpacjChunkName:test*/'./text.js')
                .then((fn) => {
                    fn()
                })
            })
        
            //预加载
            //会在模块使用之前去加载js文件
            // webpackPrefetch :true
            btn.addEventListener('click',() => {
                import(/*webpacjChunkName:test,webpackPrefetch :true*/'./text.js')
                .then((fn) => {
                    fn()
                })
            })
        
      • PWA 离线访问

            //webpack.config.js配置
        
            //安装
                // $ cnpm instal work-box-webpack-plugin -D
            //引入
                // const WorBoxWebpackPlugin = require('work-box-webpack-plugin');
        
        
            //配置
            module.exports = {
                plugins : [
                    new WorBoxWebpackPlugin({
                        /*
                            1: 使serviceworler快速启动
                            2:删除旧的serviceworker
        
                            生成有一个serviceworker 配置文件
                        */
                       clientsClaim : true,
                       skipWaiting : true,
                    })
                ]
            }
        
        
            //在入口文件js中注册serviceworker
            if('serviceworker' in navigator){
                window.addEventListener('load',() => {
                    navigator.serviceworker
                        .register('./serviceworker.js')
                        .then(() => {
                            console.log('serviceworker注册成功')
                        })
                        .catch(() => {
                             console.log('serviceworker注册失败')
                        })
                })
            }
        
            /*
                注意事项:
                    1: eslint 不识别 window / navigator全局变量
                        解决: 
                            在package.json中eslintConfig配置
                            "env" : {
                                "browser" : true
                                //支持浏览器端全局变量
                            }
        
                    2: serviceworker 必须运行在服务器上
            */
        
        
        
      • 多进程打包

            // cnpm install thread-loader -D
        
            //配置 : 在 babel中使用即可
            {
                test: /.js$/,
                exclude: /node_modules/,
                use : [
                    {
                        /*
                            开启多个进程打包:
        
                            进程启动大概在600ms 进程通信也有开销
                            只有工作消耗比较大的时候才能使用多进程打包
                        */
                        loader : 'thread-loader',
                        options : {
                            workers : 2//进程2个
                        }
                    },
                    {
                        loader: 'babel-loader',
                        options: {
                            persets: [
                                [
                                    '@babel/preset-env',
                                    {
                                        useBuildIns: 'usage',
                                        corejs: {
                                            version: 3
                                        },
                                        targets: {
                                            chrome: '60',
                                            firefox: '60',
                                            ie: '9',
                                            safari: '10',
                                            edge: '17'
                                        }
                                    }
                                ]
                            ]
                        }
                    }
                ]
            }
        
      • externals (忽略某个包进行打包 : 例如忽略引入的jquery库)

            //配置:只需要在webpack.config.js 添加 externals即可
            externals : {
                //拒绝jQuery被打包进来
                //jQuery 为 npm包的名称
                jquery : 'jQuery'
            }
        
      • DLL打包

            // 创建 webpack.dll.js文件
            // 使用dll技术对某些库 (第三方库 : jquery、react、vue ...) 进行单独打包
            const {reslove} = 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 : [
                    new webpack.DllPlugin({
                        name : '[name]_[hash]'  //映射库的暴露的内容名称
                        path : resolve(__dirname,'dll/manifest.json') //输出文件的路径
                    })
                ],
                mode : 'production'
            }
        
        
            //webpack.config.js中配置
        
            // 安装 引入 webpack   add-asset-html-webpack-plugin
        
            plugins : [
                // 告诉webpack哪些库不参与打包,同时使用时候的名称也需要变更
                new webpack.DllReferencePlugin({
                    manifest : path.resolve(__dirname,'dll/manifest.json')
                }),
                //将某个文件打包输出去,并在html中自动引入
                new AdAssetHtmlWebpackPlugin({
                    filename : path.resolve(__dirname,'dll/jquery.js')
                })
            ]
        
  • 相关阅读:
    Hibernate----面试题
    Java框架部分---面试题
    面试题---多线程
    swap分区
    Linux之格式化与挂载
    Linux下的GPT分区
    Linux下的MBR分区
    vim基础初步
    管道符,通配符以及其他特殊符号
    shell基础之脚本执行,命令别名以及快捷键等
  • 原文地址:https://www.cnblogs.com/bruce-w/p/14074156.html
Copyright © 2020-2023  润新知