<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Webpack學(xué)習(xí)筆記(優(yōu)化篇)

          共 7027字,需瀏覽 15分鐘

           ·

          2021-10-28 22:41

          webpack構(gòu)建速度和體積優(yōu)化策略

          初級分析:使用webpack內(nèi)置的stats

          stats:構(gòu)建的統(tǒng)計信息

          package.json中使用stats

          "scripts":{"build:stats":"webpack --env production --json > stats.json"...}

          Node.js中使用stats

          const webpack =require("webpack");const config =require("./webpack.config.js")("production");webpack(config,(err, stats)=>{if(err){return console.error(err);}if(stats.hasErrors()){return console.error(stats.toString("errors-only"));}  console.log(Stats);})

          ef9b4c0d47a567c5f00c429dadabe4af.webp


          stats統(tǒng)計的缺陷:顆粒度比較粗,看不出問題所在

          速度分析:使用speed-measure-webpack-plugin

          使用步驟

          安裝

          npm install --save-dev speed-measure-webpack-plugin

          代碼示例

          constSpeedMeasurePlugin=require("speed-measure-webpack-plugin");const smp =newSpeedMeasurePlugin();const webpackConfig = smp.wrap({  plugins:[newMyPlugin(),newMyOtherPlugin()]})

          9923564fb1736776e2cbbb0c51fb6973.webp


          優(yōu)點(diǎn):可以看到每個loader和插件執(zhí)行耗時

          速度分析插件作用

          分析整個打包總耗時

          每個插件和loader的耗時情況

          體積分析:使用webpack-bundle-analyzer

          webpack-bundle-analyzer分析體積

          代碼示例:

          constBundleAnalyzerPlugin=require('webpack-bundle-analyzer').BundleAnalyzerPlugin;module.exports ={  plugins:[newBundleAnalyzerPlugin();]}

          構(gòu)建完成后會在8888端口展示構(gòu)建資源大小

          可以分析哪些問題?

          ?依賴的第三方模塊文件大小?業(yè)務(wù)里面的組件代碼大小

          7167ec9c606d3c16946666ca030ffd5f.webp


          速度提升:使用高版本的webpack和Node.js

          ?構(gòu)建時間降低了60%-98%

          使用webpack4:優(yōu)化原因

          ?V8帶來的優(yōu)化(for of 替代forEach、Map和Set替代Object,includes替代indexOf)?默認(rèn)使用更快的md4 hash算法?webpacks AST可以直接從loader傳遞給AST,減少解析時間?使用字符串方法替代正則表達(dá)式

          速度提升:多進(jìn)程/多實例構(gòu)建

          多進(jìn)程/多實例構(gòu)建:資源并行解析可選方案

          ?thread-loader?parallel-webpack?HappyPack

          多進(jìn)程/多實例構(gòu)建:使用HappyPack解析資源

          原理:每次webpack解析一個模塊,HappyPack會將它及它的依賴分配給worker線程中

          代碼示例:

          exports.plugins =[newHappyPack({    id:'jsx',    threads:4,    loaders:['babel-loader']}),newHappyPack({    id:'styles',    threads:2,    loaders:['style-loader','css-loader','less-loader']})]

          fbb1a29546f5eb6a111a109aa9365ca5.webp


          多進(jìn)程/多實例構(gòu)建:使用thread-loader解析資源

          原理:每次webpack解析一個模塊,thread-loader會將它及它的依賴分配給worker線程中

          module.exports = smp.wrap({  entry: entry,  output:{    path: path.join(__dirname,'dist'),    filename:'[name]_[chunkhash:8].js'},  mode:'production',module:{    rules:[{        test:/.js$/,use:[{            loader:'thread-loader',            options:{              workers:3}},'babel-loader',]}]}})

          對進(jìn)程/多實例:并行壓縮

          方法一:使用parallel-uglify-plugin插件

          constParallelUglifyPlugin=require('webpack-parallel-uglify-plugin');module.exports ={  plugins:[newParallelUglifyPlugin({      uglifyJS:{        output:{          beautify:false,          comments:false},        compress:{          warnings:false,          drop_console:true,          collapse_vars:true,          reduce_vars:true,}}})]}

          方法二:uglifyjs-webpack-plugin開啟parallel參數(shù)

          constUglifyJsPlugin=require('uglifyjs-webpack-plugin');module.exports ={  plugins:[newUglifyJsPlugin({      uglifyOptions:{        warnings:false,        parse:{},        compress:{},        mangle:true,        output:null,        toplevel:false,        nameCache:null,        ie8:false,        keep_fnames:false},      parallel:true})]}

          方法三:terser-webpack-plugin開啟parallel參數(shù)

          constTerserPlugin=require('terser-webpack-plugin');module.exports ={  optimization:{    minimizer:[newTerserPlugin({        paralles:4})]}}

          進(jìn)一步分包:預(yù)編譯資源模塊

          分包:設(shè)置Externals

          思路:將react、react-dom基礎(chǔ)包通過cdn引入,不打入bundle中

          方法:使用html-webpack-externals-plugin

          constHtmlWebpackExternalsPlugin=require('html-webpack-externals-plugin');module.exports ={...  plugins:[newHtmlWebpackExternalsPlugin({            externals:[{module:'react',                    entry:'https://11.url.cn/now/lib/16.2.0/react.min.js',global:'React',},{module:'react-dom',                    entry:'https://11.url.cn/now/lib/16.2.0/react-dom.min.js',global:'ReactDOM',}]})]...}

          分包:預(yù)編譯資源模塊

          思路:將react、react-dom、redux、react-redux基礎(chǔ)包和業(yè)務(wù)基礎(chǔ)包打包成一個文件

          方法:使用DLLPLugin進(jìn)行分包,DllReferencePlugin對manifest.json引用

          使用DLLPlugin進(jìn)行分包

          const path =require('path');const webpack =require('webpack');module.exports ={  context: process.cwd(),  resolve:{    extensions:['.js','.jsx','.json','.less','.css'],    modules:[__dirname,'node_modules']},  entry:{    library:['react','react-dom','redux','react-redux']},  output:{    filename:'[name].dll.js',    path: path.resolve(__dirname,'./build/library'),    library:'[name]'},  plugins:[new webpack.DllPlugin({      name:'[name]',      path:'./build/library/[name].json'})]}

          使用DllReferencePlugin引用manifest.json

          在webpack.config.js引入

          module.exports ={  plugins:[new webpack.DllReferencePlugin({      manifest:require('./build/library/manifest.json')})]}

          速度提升:充分利用緩存提升二次構(gòu)建速度

          緩存目的:提升二次構(gòu)建速度

          緩存思路:

          ?babel-loader開啟緩存?terser-webpack-plugin開啟緩存?使用cache-loader或者h(yuǎn)ard-source-webpack-plugin

          速度提升:縮小構(gòu)建目標(biāo)

          目的:盡可能的少構(gòu)建模塊

          比如babel-loader不解析node_modules

          減少文件搜索范圍

          ?優(yōu)化resolve.modules配置(減少模塊搜索層級)?優(yōu)化resolve.mainFields配置?優(yōu)化resolve.extensions配置?合理使用alis

          module.exports ={  resolve:{alias:{      react: path.resolve(__dirname,'./node_modules/react/dist/react.min.js'),},    modules:[path.resolve(__dirname,'node_modules')],    extensions:['.js'],    mainFields:['main'],}}

          使用Tree Shaking擦除無用的JavaScript和Css

          tree shaking(搖樹優(yōu)化)復(fù)習(xí)

          概念:1個模塊可能有多個方法,只要其中的某個方法使用到了,則整個文件都會被打到bundle里面去,tree shaking就是只把用到的方法打入bundle,沒用到的方法會在uglify階段被擦除掉。

          使用:webpack默認(rèn)支持,在.babelrc里設(shè)置modules: false即可

          ?production mode的情況下默認(rèn)開啟

          要求:必須是ES6語法,CJS的方式不支持

          無用的CSS如何刪除掉?

          PurifyCSS:遍歷代碼,識別已經(jīng)用到的CSS class

          uncss:HTML需要通過jsdom加載,所有的樣式通過PostCSS解析,通過document.querySelector來識別在html文件里面不存在的選擇器

          在webpack中如何使用PurifyCSS?

          使用purgecss-webpack-plugin

          ?https://github.com/FullHuman/purgecss-webpack-plugin

          和mini-css-extract-plugin配合使用

          const path =require('path');const glob =require('glob');constMiniCssExtractPlugin=require('mini-css-extract-plugin');constPurgecssPlugin=require('purgecss-webpack-plugin');const PATHS ={  src: path.join(__dirname,'src')}module.exports ={module:{    rules:[{        test:/\.css/,use:[MiniCssExtractPlugin.loader,'css-loader']}]},  plugins:[newMiniCssExtractPlugin({      filename:'[name].css',}),newPurgecssPlugin({      paths: glob.sync(`${PATHS.src}/**/*`,{nodir:true})})]}

          使用webpack進(jìn)行圖片壓縮

          要求:基于Node庫的imagemin或者tinypngAPI

          使用:配置image-webpack-loader

          return{  test:/\.(png|svg|jpg|gif|blob)$/,use:[{    loader:'file-loader',    options:{      name:`${filename}img/[name]${hash}.[ext]`}},{    loader:'image-webpack-loader',    options:{      mozjpeg:{        progressive:true,        quality:65},      optipng:{        enabled:false,},      pngquant:{        quality:'65-90',        speed:4},      gifsicle:{        interlaced:false},      webp:{        quality:75}}}]}

          Imagemin的優(yōu)點(diǎn)分析

          ?有很多定制選項?可以引入更多第三方優(yōu)化插件,例如pngquant?可以處理多種圖片格式

          Imagemin的壓縮原理

          ?pngquant:是一款PNG壓縮器,通過將圖像轉(zhuǎn)換為具有alpha通道(通常比24/32位PNG文件小60-80%)的更高效的8位PNG格式,可顯著減小文件大小。?pngcrush:其主要目的是通過嘗試不同的壓縮級別和PNG過濾方法來降低PNG IDAT數(shù)據(jù)流的大小。?optipng:其設(shè)計靈感來自于pngcrush。optipng可將圖像文件重新壓縮為更小尺寸,而不會丟失任何信息。?tinypng:也是將24位png文件轉(zhuǎn)化為更小有索引的8位圖片,同時所有非必要的metadata也會被剝離掉。

          使用動態(tài)Polyfill服務(wù)

          babel-polyfill:打包后體積88k,占比較大

          構(gòu)建體積優(yōu)化:動態(tài)Polyfill

          方案優(yōu)點(diǎn)缺點(diǎn)是否采用
          babel-polyfillReact16官方推薦1、包體積200K+,難以單獨(dú)抽離Map、Set;2、項目里react是單獨(dú)引用的cdn,如果要用它,需要單獨(dú)構(gòu)建一份放在react前加載
          babel-plugin-transform-runtime能只polyfill用到的類或方法,相對體積較小不能polyfill原型上的方法,不適用于業(yè)務(wù)項目的復(fù)雜開發(fā)環(huán)境
          自己寫Map、Set的polyfill定制化高,體積小1、重復(fù)造輪子,容易在日后年久失修成為坑;2、即使體積小,依然所有用戶都要加載
          polyfill-service只給用戶返回需要的polyfill,社區(qū)維護(hù)部分國內(nèi)奇葩瀏覽器UA可能無法識別(但可以降級返回所需全部polyfill)

          Polyfill Service原理

          識別User Agent,下發(fā)不同的Polyfill

          a4ad7dea2fda60168eb0d889c86cdb4e.webp


          如何使用動態(tài)Polyfill Service

          1、polyfill.io 官方提供的服務(wù)

          2、基于官方自建polyfill服務(wù)

          //huayang.qq.com/polyfill_service/v2/polyfill.min.js?unknown=polyfill&features=Promise,Map,Set


          瀏覽 57
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天躁日日躁AAAAXXXX | 成人午夜色情无码视频app | 国产精品久久久久久久精 | 综合日逼网 | 亚洲国产精品久久久久 |