webpack學習筆記--優化

前言

瞭解了webpack的基本配置以後,接下來應該關注其優化策略。webpack的優化策略對咱們的程序有着極大的性能提高。這是我記錄學習webpack優化的文章,紀錄的同時也但願分享給你們。css

DLL動態連接庫

在開發的過程當中,咱們會引入像reactreact-dom這樣的庫,這樣的庫基本上每一次打包時它們的內容都不會改變,因此咱們引入動態連接庫。將它們打包一次,在以後的構建過程當中它們就不會被打包,打包的模塊也會使用動態連接庫裏面的代碼而不是去node_modules中取,這樣咱們的構建速度就會大大提高。下面讓咱們來看看webpack中怎麼構建動態連接庫。html

打包

咱們新建一個webpack.dll.config.js的文件,配置以下node

const path = require('path')
const DllPlugin = require('webpack/lib/DllPlugin')
module.exports = {
    entry:{
        //將react、react-dom放到動態連接庫中
        react:['react','react-dom']
    },
    output:{
        //輸出的文件名稱,[name]指的是當前動態連接庫的名稱,即react
        filename:'[name].dll.js',
        //輸出到dist目錄下
        path:path.resolve(__dirname,'dist'),
        //存動態連接庫的全局變量名稱,即_dll_react,加上_dll_防止全局變量衝突
        library:'_dll_[name]',
    },
    plugins:[
        new DllPlugin({
            //動態連接庫的全局變量名稱,須要和library一致
            name:'_dll_[name]',
            path:path.join(__dirname,'dist','[name].manifest.json')
        })
    ]
}
複製代碼

下面執行命令npx webpack --config webpack.dll.config.js,dist目錄下多了兩個文件,分別是react.dll.jsreact.manifest.json react.dll.js裏面包含React的基礎運行環境,即reactreact-dom模塊。react.manifest. json用於描述在動態連接庫文件中包含哪些模塊。react

而後再新建一個webpack.config.js文件,在打包出來的chunk塊中聲明須要引入的動態連接庫,具體配置以下webpack

const path = require('path')
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin')
module.exports = {
    entry: {
        main: './main.js'
    },
    output:{
        filename:'bundle.js',
        path:path.resolve(__dirname,'dist')
    },
    module:{
        rules:[

        ]
    },
    plugins:[
        new DllReferencePlugin({
            manifest:require('./dist/react.manifest.json')
        })
    ]
}
複製代碼

執行命令npx webpack,在dist目錄下生成bundle.jsweb

引入

而後咱們在dist目錄下新建一個index.html文件,引入打包構建出來的文件和動態連接庫。json

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    
    <script src="./react.dll.js"></script>
    <script src="./buncld.js"></script>
</body>
</html>
複製代碼

HappyPack

當文件數量變多時,webpack構建速度慢的問題會變得特別明顯。可是運行在node之上的webpack是單線程的,不能同時處理多個任務。而HappyPack可讓webpack作到這一點,它將任務分解成多個子進程去併發執行。因爲JavaScript是單線程模型,因此想要發揮多核CPU的做用只能經過多進程而不能經過多線程來實現。 接入HappyPack的代碼以下瀏覽器

const path = require('path')
const HappyPack = require('happypack');
module.exports = {
    entry: {
        main: './main.js'
    },
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [{
                test: /\.js$/,
                //以babel爲id,轉交給happypack處理
                use: ['happypack/loader?id=babel'],
            },
            {
                test: /\.css$/,
                //以css爲id,轉交給happypack處理
                use: ['happypack/loader?id=css']
            }

        ]
    },
    plugins: [
        new HappyPack({
            id: 'babel',
            loaders: ['babel-loader']
        }),
        new HappyPack({
            id: 'css',
            loaders: ['style-loader','css-loader']
        })
    ]
}
複製代碼

執行構建命令 npx webpack 從命令行的輸出能夠看出HappyPack已經生效bash

Happy[babel]: Version: 5.0.1. Threads: 3
Happy[babel]: All set; signaling webpack to proceed.
Happy[css]: Version: 5.0.1. Threads: 3
Happy[css]: All set; signaling webpack to proceed.
複製代碼

壓縮代碼

爲了提高網頁的加載速度,能夠對資源進行壓縮。服務器

壓縮JavaScript

這裏咱們會用到UglifyJS,它經過去掉無效代碼、去掉日誌輸出、縮短變量名,從而來優化咱們的代碼。 簡單的配置以下

const UglifyJSPlugin = require('webpack/lib/optimize/UglifyJsPlugin')
module.exports = {
    //以上省略。。。
    plugins: [
        //壓縮輸出的 JavaScript 代碼
        new UglifyJSPlugin({
            compress: {
                //在 UglifyJS 刪除沒有用到的代碼時不輸出警告
                warnings: false,
                //刪除全部 console 語句, 能夠兼容IE瀏覽器
                drop_console: true,
                //內嵌己定義可是隻用到一次 的變量
                collapse_vars: true,
                //提取出現了屢次可是沒有定義成變量去 用的靜態值
                reduce_vars: true,
                output: {
                    //最緊湊的輸出
                    beautify: false,
                    //刪除全部註釋
                    comments: false,
                }
            }
        })
    ]
複製代碼

壓縮CSS

CSS也能夠向JavaScript同樣被壓縮,這裏用到的工具是cssnanocssnano的意義不單單是刪除空格,它能夠理解CSS代碼。例如 margin:10px 20px 10px 20px 會被壓縮爲 margin:10px 20px 基本配置以下

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-plugin')
module.exports = {
    //以上省略。。。。
    module: {
        rules: [{
            test: /\.css$/,
            use: [ExtractTextPlugin.extract({
                use: ['style-loader', 'css-loader?minimize']
            })]
        }]
    },
    plugins:[
        new HtmlWebpackPlugin({
            template:'./index.html',
            filename:'index.html'
        }),
        new ExtractTextPlugin({
            filename: '[name]_[contenthash:8].css'
        })
    ]
}

複製代碼

提取公共代碼

若是將多個頁面的公共代碼抽離成單獨的文件,就能優化一些問題。例如相同的資源被重複加載,浪費用戶的流量和服務器的成本。每一個頁面要加載的資源太大,致使網頁首屏加載緩慢,影響用戶體驗。 基本配置以下,此配置主要針對多頁面。單頁就不存在於公共代碼這一說法了。

import 'react'
import 'react-dom'
import './index.css' //每一個頁面都用到的樣式
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin')
module.exports = {
    module: {
        entry: './main.js',
        rules: [{
            test: /\.css$/,
            use: [ExtractTextPlugin.extract({
                use: ['style-loader', 'css-loader?minimize']
            })]
        }]
    },
    plugins: [
        new CommonsChunkPlugin({
            //從已有的common和base兩個現成的chunks中提取公共部分 
            chunks: ['common', 'base'],
            //將公共部分放到base中 這樣配置以後 common會變小,由於公共部分都跑到了base裏,而base不變
            name: 'base'
        })
    ]
}
複製代碼

爲了能使網頁運行,以網頁A爲例,除了打包出來的A頁面的JavaScript代碼還需引入公共部分代碼

<script src= 'base.js'></script>
<script src='common.js'></script>
<script src='a.js'></script> 
複製代碼

按需加載

單頁應用首次渲染緩慢,一個很重要的緣由是一次性加載了全部功能對應的代碼。這個時候若是採用按需加載,咱們網站的性能將會大大提高。 在webpack裏,按需加載能夠這樣來寫。例如咱們只打包出了一個bundle.js。在bundle.js中,有這麼一段代碼

window.document.getElementById('button').addEventListener('click',()=>{
    import('./show').then(show=>{
        show('webpack')
    })
})
複製代碼

show.js

module.exports= function (content) {
    window.aleat(`hello ${content}`)
}
複製代碼

webpack中內置了import語句的支持,當遇到這樣的語句時,首先會生成一個新的chunk,而後觸發import的時候再去加載這個chunk,返回的是一個Promise對象,在加載成功時使用then方法進行下面的操做,爲了讓webpack正確打包chunk,配置文件中需加入

output:{
    //從entry打包生成的chunk
    filename:'[name].js',
    //動態加載生成的chunk
    chunkFileName:'[name].js'
}
複製代碼

最後

webpack的優化配置還有不少,這裏只記錄了我平時經常使用的,具體詳情還請查閱官方文檔。

相關文章
相關標籤/搜索