webpack基礎(chǔ)使用(五)

十六、加載構(gòu)建優(yōu)化
  1. 懶加載
// 按需加載
oBtn.addEventListener('click', () => {
  import('./utils').then(({ default: element }) => {
    console.log(element)
    document.body.appendChild(element)
  })
})
  1. 預(yù)獲取 & 預(yù)讀取
// 按需加載
oBtn.addEventListener('click', () => {
  import(
    /* webpackChunkName:'utils' */
    /* webpackPreload:true */
    './utils').then(({ default: element }) => {
      console.log(element)
      document.body.appendChild(element)
    })
})

//  /* webpackPrefetch:true */

與 prefetch 指令相比,preload 指令有許多不同之處:

preload chunk 會在父 chunk 加載時,以并行方式開始加載。prefetch chunk 會在父 chunk 加載結(jié)束后開始加載。
preload chunk 具有中等優(yōu)先級,并立即下載。prefetch chunk 在瀏覽器閑置時下載。
preload chunk 會在父 chunk 中立即請求,用于當(dāng)下時刻。prefetch chunk 會用于未來的某個時刻。
瀏覽器支持程度不同。

preload 可以使用在首頁很可能需要點擊的按鈕上面

  1. CDN優(yōu)化
    優(yōu)化打包速度, 使用CDN加載提高性能.
// index.html
  <!-- cdn可以在對應(yīng)官網(wǎng)查找 -->
  <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

// webpack.common.js
output: { 
    // publicPath: '配置自己的CDN地址'
  },
    // 排除lodash,加快打包速度
    // 使用CDN加載lodash提高性能
    // '_'是固定寫法
    externals: {
      lodash: '_'
    }
  1. dll庫
    把大的, 不經(jīng)常變的打包成一個dll庫, 然后使用方直接加載使用。
const path = require('path')
const webpack = require('webpack')
const TerserPlugin = require('terser-webpack-plugin')

module.exports = {
  mode: "production",
  // 需要打包的東西
  entry: {
    react: ['react', 'react-dom']
  },
  output: {
    // 輸出路徑
    path: path.resolve(__dirname, 'dll'),
    filename: 'dll_[name].js',
    // 暴露從入口導(dǎo)出的內(nèi)容, 給使用地方的命名
    library: 'dll_[name]'
  },
  optimization: {
    minimizer: [
      new TerserPlugin({
        // 使用Terser壓縮
        // minimize: true,
        // 去除注釋文件
        extractComments: false
      }),
    ],
  },
  plugins: [
    // 生成dll的插件
    new webpack.DllPlugin({
      name: 'dll_[name]',
      // manifest負責(zé)映射到具體文件
      path: path.resolve(__dirname, './dll/[name].manifest.json')
    })
  ]
}
  1. 使用dll庫
    注意dll庫只是幫助我們避免打包了, js里面導(dǎo)入文件不變。
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin')

const commonConfig = {
  /*省略*/
  plugins: [
    new webpack.DllReferencePlugin({
      context: resolveApp('./'),
      // 相對于context的路徑
      manifest: resolveApp('./dll/react.manifest.json')
    }),
    // 
    new AddAssetHtmlPlugin({
      // 這個插件目前之后在html里面找auto目錄
      outputPath: 'auto',
      // 拷貝一份到dist, 同時添加html引用, html從auto里面找
      filepath: resolveApp('./dll/dll_react.js')
    })
  ]
}
  1. css抽取和壓縮
    css 150KB再考慮分包,因為這樣增加一次加載。
// webpack.prod.js
// 抽取獨立css
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
// 壓縮css
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")

module.exports = {
  mode: 'production', 
  optimization: {
    minimizer: [
      new CssMinimizerPlugin()
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/[name].[hash:8].css'
    })
  ]
}

// webpack.common.js
// 抽取獨立css
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
          {
            test: /\.css$/,
            use: [
              isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
              {
                loader: 'css-loader',
                options: {
                  // 代表向前找一個loader處理 
                  esModule: false
                }
              }, 'postcss-loader'
            ]
          }
  1. 作用域提升
    作用域提升只能知道esModule的語法
// webpack.prod.js
const webpack = require('webpack')

module.exports = {
  mode: 'production',
  plugins: [
    /* 省略 */
    new webpack.optimize.ModuleConcatenationPlugin()
  ]
}
  1. TreeShaking
    a. usedExports 標記不需要使用的代碼
optimization: {
   // 標記不需要使用的代碼:/* unused harmony export foo2 */
    usedExports: true,
    // 樹搖, TerserPlugin移除不使用的代碼
    minimize: true,
  }

b. sideEffects 識別副作用
對于不需要使用的類,有選擇的跳過,去除對應(yīng)副作用

// utils.js
window.utils = '1111'
// index.js
import './utils'
//1. 是可以打印的
console.log(window.utils, '<------')

// package.json 代表代碼都是沒有副作用的, 如果沒有使用就移除
"sideEffects": false
//2. 打印為undefined
console.log(window.utils, '<------')

// package.json 代表代碼都是有副作用的,即使沒有使用也不能移除
//3. 使用副作用
"sideEffects": [
    "./src/title.js"
  ]

正常Css文件,我們是需要使用副作用的 ,可以在package.json里面配置,不過一般在webconfig文件里面配置


image.png

c. PurgeCSSPlugin 針對Css文件進行樹搖
yarn add purgecss-webpack-plugin glob --dev
注意及時代碼注釋,主要注釋里面有對應(yīng)標簽,也算使用。

// webpack.prod.js

const PurgeCSSPlugin = require('purgecss-webpack-plugin')
const resolveApp = require('./paths')
const glob = require('glob')

module.exports = {
  plugins: [
    new PurgeCSSPlugin({
      // 查找src里面所有文件
      paths: glob.sync(`${resolveApp('./src')}/**/*`, { nodir: true }),
      safelist: function () {
        return {
          // 下面css標簽不會被樹搖
          standard: ['body', 'html', 'ef']
        }
      }
    })
  ]
}
  1. 壓縮部署,http請求的時候節(jié)省資源
    yarn add compression-webpack-plugin --dev
// webpack.prod.js

const CompressionPlugin = require("compression-webpack-plugin")

module.exports = {
  plugins: [
      new CompressionPlugin({
      // 只壓縮css 和 js 文件
      test: /\.(css|js)$/,
      // 默認0.8 只有壓縮比到0.8才生成壓縮文件
      minRatio: 0.8,
      // 文件大小, 開始壓縮
      threshold: 0,
      // 壓縮格式
      algorithm: 'gzip'
    })
  ]
}
  1. inlineChunkHtmlPlugin 可以向Html注入內(nèi)容
    有時候比較小的文件,可以直接在html中使用,而不需要引入一次。
    yarn add inline-chunk-html-plugin --dev
// webpack.prod.js
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  plugins: [
      // 把runtime文件直接注入到 需要的Html文件中
      new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime.*\.js/])
  ]
}
  1. webpack 打包 三方庫
  output: {
    filename: 'sy_utils.js',
    path: path.resolve(__dirname, 'dist'),
    /// umd 所有模塊化結(jié)合
    libraryTarget: 'umd',
    // library使用的名稱
    library: 'syUtil', 
    // 調(diào)用全局變量
    globalObject: 'this'
  }
  1. 打包時間和內(nèi)容分析
// 時間分析
// webpack.common.js
// 注意兼容性, 需要mini-css-extract-plugin降級到1.3.6
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin")
const smp = new SpeedMeasurePlugin()
module.exports = (env) => {
  /**/
  return smp.wrap(mergeConfig)
}

// 內(nèi)容分析
// webpack.prod.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

  plugins: [
    /**/
    new BundleAnalyzerPlugin()
  ]
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容