做者:餘韻之
咱們可使用懶加載的方式引入模塊,好比說當觸發了某個條件,在經過import的方式引入模塊。這樣可使得項目的性能會更加的好。css
舉個例子:html
當咱們點擊頁面的時候,纔會去引入lodash模塊,這裏 import()返回的是promise前端
async function getComponent() { const {default: _} = await import(/* webpackChunkName:"lodash" */'lodash') const element = document.createElement('div') element.innerHTML = _.join(['y', 'kk'], '-'); return element; } document.addEventListener('click', () => { getComponent().then(element => { document.body.appendChild(element) }) })
一樣的路由懶加載的意思,表示當咱們監聽到路由變化了,纔會去引入對應的頁面模塊。node
所以能夠知道,Chunk是什麼?打包生成幾個JS文件,就是幾個Chunkjquery
Shimming:在打包過程當中,有時候須要對代碼兼容。這種兼容不侷限於瀏覽器高低版本。webpack
舉個例子git
每一個文件都是一個模塊,每一個模塊都應該引入本身的依賴才能使用該依賴。github
import $ from 'jquery' export function setBackground(){ $('body').css('background','red') }
可是這樣的話,每一個文件都要寫一遍web
import $ from 'jquery'
所以可使用墊片的方式來自動配置npm
plugins:[ new webpack.ProvidePlugin({ $:'jquery', _join:['lodash','join'] }) ]
當咱們配置了上述內容,那麼意味着當運行代碼的時候看到
因而咱們能夠直接這些一個文件模塊使用
export function setBackground(){ $('body').css('background', _join(['green'], '')) }
當咱們打包生成了
index.html main.js vendors.js
客戶端從服務端拿到了兩個js文件,會保存在瀏覽器裏。客戶端刷新後瀏覽器會先從緩存裏獲取。
當開發修改了代碼,從新打包,生成了上述三個同名文件時,用戶刷新後仍然是原來的代碼並無更新。
這樣如何解決呢?
開發環境由於是熱更新的,因此本地調試能夠不添加,
生產環境在output裏改成
output: { filename: '[name].[contentHash].js', chunkFilename: '[name].[contentHash].js' }
contentHash 表示只要不改變源代碼的內容,那麼contentHash所產生的hash值是不會變的。若是代碼是分割成不一樣的chunk,某個chunk沒有修改,該chunk的文件名contentHash也不會修改
同時作了代碼分割的參數最好也配置一下
optimization.splitChunks.cacheGroup.vendors.filename = 'vendors.[contentHash].js'
可能老的版本即便不改內容,contentHash值也會改變,這個時候能夠配置
optimization: { runtimeChunk:{ name:'runtime' } }
新版本添加這個runtimeChunk也是沒有問題的,此時打包會多出一個runtime.xxxxxxx.js文件
這是怎麼回事呢?
由於在舊的webpack版本里main.js(業務邏輯) 和 vendors.js(第三方庫) 之間是存在關聯的,這部分的處理代碼放在mainfest,雖然沒有改變代碼,但在舊版本的webpack裏 mainfest 包和包之間的關係每次打包可能會變化,當咱們配置了runtimeChunk的時候就把mainfest這塊關係相關的代碼抽離出來了放在runtime.js裏
所以這樣就解決了這個兼容老版本的問題。
正常打包的話,會把CSS文件一塊兒打包的main.js文件,如何進行CSS代碼分割呢?
但這個插件有一個缺點,目前不支持熱更新,因此適合線上環境作打包
配置方式安裝依賴
yarn add mini-css-extract-plugin
在生產環境的webpack.config.js配置
const MiniCssExtractPlugin = require('mini-css-extract-plugin') module:{ rules:[ { test: /\.scss$/, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { importLoaders: 2 } }, 'sass-loader', 'postcss-loader' ] }, { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader' ] } ] }, plugins: [ new MiniCssExtractPlugin({ filename: "[name].css", //index.html直接引入的文件 chunkFilename: "id.css" // 間接引用的文件 }) ]
注意 若是此時使用了tree shaking 看看 package.json 裏 sideEffects 配置。若是爲false那麼css代碼是沒有分割的。須要把css tree shaking排除在外。修改以下:
"sideEffects": [ "*.css" ],
安裝依賴
yarn add optimize-css-assets-webpack-plugin -D
生產環境
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin') optimization:{ minimizer:[new OptimizeCSSAssetsPlugin({})] }
生成webpack打包分析json
webpack --profile --json > stats.json --config ./build/webpack.dev.js
而後把生成的stats.json放入相關的分析網站就能夠看到可視化的數據。固然也能夠配置analyzer
安裝依賴
npm install webpack-bundle-analyzer --save-dev
在webpack.config.js配置
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; module.exports = { ... configureWebpack: { plugins: [ new BundleAnalyzerPlugin({ // 能夠是`server`,`static`或`disabled`。 // 在`server`模式下,分析器將啓動HTTP服務器來顯示軟件包報告。 // 在「靜態」模式下,會生成帶有報告的單個HTML文件。 // 在`disabled`模式下,你可使用這個插件來將`generateStatsFile`設置爲`true`來生成Webpack Stats JSON文件。 analyzerMode: 'server', // 將在「服務器」模式下使用的主機啓動HTTP服務器。 analyzerHost: '127.0.0.1', // 將在「服務器」模式下使用的端口啓動HTTP服務器。 analyzerPort: 8888, // 路徑捆綁,將在`static`模式下生成的報告文件。 // 相對於捆綁輸出目錄。 reportFilename: 'report.html', // 模塊大小默認顯示在報告中。 // 應該是`stat`,`parsed`或者`gzip`中的一個。 // 有關更多信息,請參見「定義」一節。 defaultSizes: 'parsed', // 在默認瀏覽器中自動打開報告 openAnalyzer: true, // 若是爲true,則Webpack Stats JSON文件將在bundle輸出目錄中生成 generateStatsFile: false, // 若是`generateStatsFile`爲`true`,將會生成Webpack Stats JSON文件的名字。 // 相對於捆綁輸出目錄。 statsFilename: 'stats.json', // stats.toJson()方法的選項。 // 例如,您可使用`source:false`選項排除統計文件中模塊的來源。 // 在這裏查看更多選項:https: //github.com/webpack/webpack/blob/webpack-1/lib/Stats.js#L21 statsOptions: null, logLevel: 'info' // 日誌級別。能夠是'信息','警告','錯誤'或'沉默'。 }) ] }, ... };
使用方式 在打包或者啓動的時候加 --report
npm run serve --report npm run build --report
關注代碼使用率:一開始不會執行的代碼不要加載出來,而是當交互了再去加載。
webpack但願儘量使用異步加載模快在第一次加載提升性能,而同步是第二次加載了增長緩存對性能的提高是有限的。
document.addEventListener('click', () => { import('./click.js').then(({default:func}) => { func() }) })
注意 但這樣會存在一個問題,就是當用戶點擊交互了才下載代碼可能會有一點小小的延遲,如何解決這個問題?
解決方案就是 : prefetching/preloading
只須要在代碼添加以下內容便可:
document.addEventListener('click', () => { import(/* webpackPrefetch:true */'./click.js').then(({default:func}) => { func() }) })
當用戶點擊了,仍然會下載click.js文件,可是使用的時間會很是短,由於以前已經下載過了有了緩存了。
document.addEventListener('click', () => { import(/* webpackPreload:true */'./click.js').then(({default:func}) => { func() }) })
所以性能優化最好去考慮代碼的使用率更高。
對 Electron 感興趣?請關注咱們的開源項目 Electron Playground,帶你極速上手 Electron。咱們每週五會精選一些有意思的文章和消息和你們分享,來掘金關注咱們的 曉前端週刊。
咱們是好將來 · 曉黑板前端技術團隊。
咱們會常常與你們分享最新最酷的行業技術知識。
歡迎來 知乎、 掘金、 Segmentfault、 CSDN、 簡書、 開源中國、 博客園 關注咱們。