美文网首页
webpakc性能优化

webpakc性能优化

作者: 热心市民萝卜先生 | 来源:发表于2021-02-18 16:51 被阅读0次

webpakc性能优化

  • 开发环境性能优化
    1.优化打包构建速度
    2.优化代码调试
  • 生产环境性能优化
    1.优化打包构建速度
    2.优化代码运行的性能
一、HMR:hot modules replacement 热模块替换/模块热替换
  • 作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有),提升构建速度

  • 样式文件:可以使用HMR功能,因为style-loader内部实现了

  • js文件:默认不能使用HMR功能,

  • html文件:默认不能使用HMR功能

    改变entry,[ './src/index.js','./src/index.html'],就可以开启HMR功能,html只有一个文件,每次重新打包会刷新
    
devServer:{
    contentBase:resolve(__dirname,'build'),
    compress:true,
    port:3000,
    open:true
    //开启HMR功能
    hot:true
}
//新建print.js
//修改index.js
if(module.hot){
    //必须开启HMR功能,才会执行到这个函数
   module.hot.accept('./print.js',function(){
       //监听print.js文件是否发生变化
       print();
   })
}
二、source-map:一种提供源代码到构建后代码映射技术
devtool:'eval-source-map'

source-map:一种提供源代码到构建后代码映射技术(如果构建后代码出错,通过映射可以追踪到源代码错误)

值:[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
   source-map               :外联
     //错误代码准确信息  和  源代码的错误位置(精确到列)
   inline-source-map        :内联,只生成一个内联的source-map
     //错误代码准确信息  和  源代码的错误位置(精确到列)
   hidden-source-map        :外联
     //错误代码准确信息  和  构建代码的错误位置(只有构建后的代码)
   eval-source-map          :内联,每个文件都生成对应的source-map文件,都在eval
     //错误代码准确信息  和  源代码的错误位置(精确到列)
   nosources-source-map     :外联
     //错误代码准确信息  和  没有源代码信息
   cheap-source-map         :外联
     //错误代码准确信息  和  源代码的错误位置(精确到行)
   cheap-module-source-map  :外联
     //错误代码准确信息  和  没有源代码信息,module会将loader的source-map加入
                                      
   内联和外联的区别:1.外部生成了文件,内联没有;2.内联构建速度更快
   
   开发环境:速度快,调试更友好 ----->eval-source-map/ eval-cheap-module-source-map
     速度快
       eval-cheap-source-map
       eval-source-map
     调试友好
       source-map
       cheap-module-source-map
       cheap-source-map
   生产环境:源代码要不要隐藏,调试要不要更友好----->source-map/cheap-module-source-map
     //内联会让代码体积变大,所以再生产环境下不用内联
     源代码要不要隐藏
       nosources-source-map  全部隐藏
       hidden-source-map  只隐藏源代码,会提示构建后代码错误信息
     调试要不要更友好
       source-map
三、oneof,以下loader只会匹配一个
//不能有2个配置处理同一类型的文件
//这里匹配2个js,将一个js提出与oneof平级,enforce优先处理
module: {
  rules: [
    {
        test: /\.js$/,
        exclude: /node-modules/,
        enforce: 'pre', //优先语法检查
        loader: 'eslint-loader',
        options: {
            fix: true
        }
    },
    {
      oneof: [
        {
          test: /\.css$/,
          use: [...commonCssLoader]
        },
        {
          test: /\.less$/,
          use: [...commonCssLoader, 'less-loader']
        },
        {
          test: /\.js$/,
          exclude: /node-modules/,
          loader: 'babel-loader'
        }
      ]
    }
  ]
}
四、cache缓存
  1. babel缓存

    优点:第二次打包的速度更快

    cacheDirectory:true

  2. 文件资源缓存

    优点:代码上线运行缓存更好使用

    1. hash:webpack每次构建会生成一个唯一的hash值

      问题:js和css的hash值还是一样,如果重新打包会导致所有的缓存失效(可能改变一个文件)

    2. chunkhash:根据chunk生成的hash值。如果打包来源同一个chunk,那么hash值就一样

      问题:js和css的hash值还是一样

    3. contenthash:根据文件的内容生成hash值。不同的文件hash值一定不一样

//babel缓存
{
    test:/\.js$/
    exclude:/node-modules/
    loader:'babel-loader'
    options:{
        parsets:[
            [
                '@babel/parset-env'
                {
                    useBuiltIns:'usage'
                    corejs:{version:3},
                    targets:{
                        chrome:'60',
                        firefox:'50'
                    }
                }
            ]
        ],
        //开启babel缓存
        //第二次构建会读取之前的缓存
        cacheDirectory:true
    }
}
五、tree shaking:去除无用代码

前提:1、使用ES6模块化。2、必须在production模式下。满足这2个条件自动开启

作用:减少代码体积,构建速度更快。

在package.json中配置

"sideEffects":false 所有的代码都没有副作用(都能进行tree shaking)
问题:可能会把   css  /  @babel/polyfill 文件干掉
"sideEffects":["*.css","*.less"]
六、code split:代码分割
//生产环境配置
const { resolve } = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  //单入口
  //entry: './src/js/index.js',
  //多入口
  entry:{
    //有一个入口,最终输出就有一个bundle
    index:'./src/js/index.js',
    test:'./src/js/test.js'
  },
  output: {
    //[name]:取当前文件名
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseInlineTagWhitespace: true,
        removeComments:true
      }
    })
  ],
  mode: 'production'
}
//生产环境配置
const { resolve } = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  //多入口
  entry:{
    index:'./src/js/index.js',
    test:'./src/js/test.js'
  },
  //如果2个js同时引入JQ,打包生成3个chunk
  output: {
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseInlineTagWhitespace: true,
        removeComments:true
      }
    })
  ],
  //1.可以将node-modules中的代码单独打包成一个chunk最终输出
  //2.自动分析多入口chunk中,有没有公共的文件,如果有会单独打包成一个chunk
  optimization:{
      splitChunks:{
          chunks:'all'
      }
  },
  mode: 'production'
}
//生产环境配置
const { resolve } = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry:'./src/js/index.js'
  output: {
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseInlineTagWhitespace: true,
        removeComments:true
      }
    })
  ],
  //可以将node-modules中的代码单独打包成一个chunk最终输出
  optimization:{
      splitChunks:{
          chunks:'all'
      }
  },
  mode: 'production'
}

//index.js
/*
    通过js代码,让某个文件被单独打包成一个chunk
*/
/*webpackChunkName:'test'*/    设置文件名
imoprt (/*webpackChunkName:'test'*/'./test').then(({mul,count})=>{
    //文件加载成功
    console.log(mul(2,3))
}).catch(()=>{
    //文件加载失败
})
七、lazy loading:懒加载
//懒加载:当文件需要使用时才加载
//预加载 prefetch:会使用之前,提前加载js文件   webpackPrefetch:true
//正常加载:并行加载(同一时间加载多个文件)
imoprt(/* webpackChunkName:'test',webpackPrefetch:true*/ './test').then(({mul})=>{
    console.log(mul(2,3))
})
八、PWA:渐进式网络应用开发程序(离线可访问)
//生产环境配置
const { resolve } = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const optimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

const workboxWebpackPlugin = require('workbox-webpack-plugin')

//指定node环境变量
//process.env.NODE_ENV = 'development'

const commonCssLoader = [
  MiniCssExtractPlugin.loader,
  'css-loader',
  {
    //还需要在package.json中配置browserslist
    /*
      "browserslist": {
        "development": [
          "last 1 chrome version",
          "last 1 firefox version",
          "last 1 safari version"
        ], 
        "production": [
          ">0.2%",
          "no dead",
          "no op_mini all"
        ]
      },
    */
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      plugins: () => [
        require('postcss-preset-env')()
      ]
    }
  }
]

module.exports = {
  entry: './src/index.js',
  output: {
     filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [{
        test: /\.css$/,
        use: [...commonCssLoader]
      },
      {
        test: /\.less$/,
        use: [...commonCssLoader, 'less-loader']
      },
      {
        //需要在package.json中配置eslintConfig--->airbnb
        /*
          "eslintConfig": {
            "extends": "airbnb-base",
            "env":{
                "browser":true
            }
          }
        */
        test: /\.js$/,
        exclude: /node-modules/,
        enforce: 'pre', //优先语法检查
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        test: /\.js$/,
        exclude: /node-modules/,
        loader: 'babel-loader', //将高版本的js转为ES5
        options: {
          presets: [
            [
              '@babel-loader',
              {
                useBuiltIns: 'usage',
                corejs: {
                  version: 3
                },
                targets: {
                  chrome: '60',
                  firefox: '50'
                }
              }
            ]
          ]
        }
      },
      {
        test: /\.(jpg|png|gif)$/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          esModule: false,
          name: '[hash:10],[ext]',
          outputPath: 'images'
        }
      },
      {
        test: /\.html$/,
        loader: 'html-loader'
      },
      {
        exclude: /\.(css|less|html|js|jpg|png|gif)$/,
        loader: 'file-loader',
        options: {
          name: '[hash:10],[ext]',
          outputPath: 'media'
        }
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/bulit.css'
    }),
    new optimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseInlineTagWhitespace: true,
        removeComments:true
      }
    }),
    new workboxWebpackPlugin.GenerateSW({
        /**
        * 1.帮助serviceWorker快速启动
        * 2.删除旧的serviceWorker
        *
        * 生成一个serviceworker文件
        */
        clientClaim:true,
        skipWaiting:true
    })
  ],
  mode: 'production',
  devtool:'source-map' 
}
//index.js

/**
* 1.eslint不认识window,navigtor等全局变量
* 解决:需要在package.json中修改eslintConfig配置
* "evn":{
*   "browser":true
* }
* 2.必须在服务器上运行
*/

//在入口文件中注册serviceWorker
//处理兼容性问题
if('serviceWorker' in navigator){
    window.addEventListente('load',()=>{
        navigator.serviceWorker.register('/service-worker.js').then(()=>{
            console.log('serviceWorker注册成功')
        }).catch(()=>{
            console.log('serviceWorker注册失败')
        })
    })
}
九、多进程打包
//thread-loader,开启多进程打包,启动大概600ms,只有工作消耗时间较长才会开启多进程打包
//npm install thread-loader -D
{
    test:/\.js$/
    exclude:/node-modules/,
    use:[
        {
            //开启多进程打包
            loader:'thread-loader',
            options:{
                workers:2,//开启两个进程
            }
        },
        {
            loader:'babel-loader',
            options:{
                presets: [
                [
                  '@babel-loader',
                  {
                    useBuiltIns: 'usage',
                    corejs: {
                      version: 3
                    },
                    targets: {
                      chrome: '60',
                      firefox: '50'
                    }
                  }
                ]
              ]
            }
        }
    ]
}
十、externals防止将某些包打包输出到bundle里面,不需要打包,直接通过CDN引入
const { resolve } = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')

module.exports={
    entry:'./js/index.js',
    output:{
        filename:'./js/[name].[contenthash:10].js',
        path:resolve(__dirname,'build')
    },
    plugins:[
        new htmlWebpackPlugin({
            template:'./src/index.html',
            minfy:{
                collapseInlineTagWhitespace: true,
                removeComments:true
            }
        })
    ],
    mode:'production',
    externals:{
        //拒绝jquery被打包进来
        jquery:'jQuery'
    }
}
十一、dll,将第三方库单独打包,直接引入
//webpack.dll.js
/* 使用dll技术,对第三方库(jQuery,vue,react...)单独打包 */

const {resolve} = require('path')
const webpack = require('webpack')

module.export = {
    entry:{
        //打包生成得name,要打包得库
        jquery:['jquery']
    },
    output:{
        filename:'[name].js',
        path:resolve(__dirname,'dll'),
        library:'[name]_[hash:10]'//打包得库,向外暴露得内容名字
    },
    plugins:[
        //打包生成一个manifest.json文件 ---》 提供jQuery得映射
        new webpack.DllPlugin({
            name:'[name]_[hash:10]',//映射库得暴露名称
            path:resolve(__dirname,'dll/manifest.json')//输出文件得目录
        })
    ],
    mode:'production'
}
//webpack.config.js
const { resolve } = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')

module.exports={
    entry:'./src/index.js',
    output:{
        filename:'js/[name].[contenthash:10].js',
        path:resolve(__dirname,'build')
    },
    plugins:[
        new htmlWebpackPlugin({
            template:'./src/index.html',
            minfy:{
                collapseInlineTagWhitespace: true,
                removeComments:true
            }
        }),
        //告诉webpack那些库不打包,同时使用时得名称也在变
        new webpack.DllReferencePlugin({
            manifest:resolve(__dirname,'dll/manifest.json')
        }),
        //将第三方库单独打包,并在html自动引入
        new AddAssetHtmlWebpackPlugin({
            filepath:resolve(__dirname,'dll/jquery.js')
        })
    ],
    mode:'production'
}

性能优化总结

一、webpack性能优化
  • 开发环境性能优化
  • 生产环境性能优化
二、开发环境性能优化
  • 优化打包构建速度
    • HRM
  • 优化代码调试
    • source-map
      • 开发环境:eval-source-map || eval-cheap-module-source-map
      • 生产环境:source-map || cheap-module-source-map
三、生产环境性能优化
  • 优化打包构建速度
    • oneOf
    • babel缓存
    • 多进程打包
    • externals,
    • dll
  • 优化代码运行得性能
    • 缓存(hash || chunkhash || contenthash)
    • thee shaking(1、使用ES6模块化。2、必须在production模式下。满足这2个条件自动开启。)
    • code split
    • lazy loading
    • pwa

相关文章

  • webpakc性能优化

    webpakc性能优化 开发环境性能优化1.优化打包构建速度2.优化代码调试 生产环境性能优化1.优化打包构建速度...

  • Android性能优化 - 消除卡顿

    性能优化系列阅读 Android性能优化 性能优化 - 消除卡顿 性能优化 - 内存优化 性能分析工具 - Tra...

  • Android性能优化 - 内存优化

    性能优化系列阅读 Android性能优化 性能优化 - 消除卡顿 性能优化- 内存优化 性能分析工具 - Trac...

  • 前端性能优化(中)

    性能优化调研系列文章 《前端性能优化(上)》 《前端性能优化(中)》 《前端性能优化(下)》 《前端性能优化(上)...

  • 前端性能优化(下)

    性能优化调研系列文章 《前端性能优化(上)》 《前端性能优化(中)》 《前端性能优化(下)》 《前端性能优化(中)...

  • Awesome Extra

    性能优化 性能优化模式 常见性能优化策略的总结 Spark 性能优化指南——基础篇 Spark 性能优化指南——高...

  • 常用的后端性能优化六种方式:缓存化+服务化+异步化等

    性能优化专题 前端性能优化 数据库性能优化 jvm和多线程优化 架构层面优化 缓存性能优化 常用的后端性能优化六大...

  • webpack 性能优化

    webpack性能优化 开发环境性能优化 生产环境性能优化 开发环境性能优化 优化打包构建速度 优化调试功能 生产...

  • iOS性能优化 - 整理

    本文主要包含: 性能优化 - 卡顿性能优化 - 耗电优化性能优化 - APP启动优化安装包瘦身 一  性能优化 -...

  • 【React.js 20】React性能优化

    React性能优化 React性能优化主要分三块: React 组件性能优化 属性传递优化针对单组件性能优化,很多...

网友评论

      本文标题:webpakc性能优化

      本文链接:https://www.haomeiwen.com/subject/apknxltx.html