zoukankan      html  css  js  c++  java
  • 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')
                })
            ]
        
  • 相关阅读:
    在SQLite中使用索引优化查询速度
    SQLite支持的SQL数据操作
    left (outer) join , right (outer) join, full (outer) join, (inner) join, cross join 区别
    深入理解Android内存管理原理(六)
    Merge Sorted Array
    Sort Colors
    Construct Binary Tree from Preorder and Inorder Traversal
    Binary Tree Postorder Traversal
    Symmetric Tree
    Rotate Image
  • 原文地址:https://www.cnblogs.com/bruce-w/p/14074156.html
Copyright © 2011-2022 走看看