3. webpack 配置、性能優(yōu)化和 babel

一、 webpack 基本配置
image.png
image.png

image.png

image.png
  1. path.js
const path = require('path')

const srcPath = path.join(__dirname, '..', 'src')
const distPath = path.join(__dirname, '..', 'dist')

module.exports = {
    srcPath,
    distPath
}

  1. webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { srcPath, distPath } = require('./paths')

module.exports = {
    entry: path.join(srcPath, 'index'),
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: ['babel-loader'],
                include: srcPath,
                exclude: /node_modules/
            },
            // {
            //     test: /\.vue$/,
            //     loader: ['vue-loader'],
            //     include: srcPath
            // },
            // {
            //     test: /\.css$/,
            //     // loader 的執(zhí)行順序是:從后往前(知識點(diǎn))
            //     loader: ['style-loader', 'css-loader']
            // },
            {
                test: /\.css$/,
                // loader 的執(zhí)行順序是:從后往前
                loader: ['style-loader', 'css-loader', 'postcss-loader'] // 加了 postcss
            },
            {
                test: /\.less$/,
                // 增加 'less-loader' ,注意順序
                loader: ['style-loader', 'css-loader', 'less-loader']
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: path.join(srcPath, 'index.html'),
            filename: 'index.html'
        })
    ]
}
  1. webpack.dev.js
const path = require('path')
const webpack = require('webpack')
const webpackCommonConf = require('./webpack.common.js')
const { smart } = require('webpack-merge')
const { srcPath, distPath } = require('./paths')

module.exports = smart(webpackCommonConf, {
    mode: 'development',
    module: {
        rules: [
            // 直接引入圖片 url
            {
                test: /\.(png|jpg|jpeg|gif)$/,
                use: 'file-loader'
            }
        ]
    },
    plugins: [
        new webpack.DefinePlugin({
            // window.ENV = 'development'
            ENV: JSON.stringify('development')
        })
    ],
    devServer: {
        port: 8080,
        progress: true,  // 顯示打包的進(jìn)度條
        contentBase: distPath,  // 根目錄
        open: true,  // 自動(dòng)打開瀏覽器
        compress: true,  // 啟動(dòng) gzip 壓縮

        // 設(shè)置代理
        proxy: {
            // 將本地 /api/xxx 代理到 localhost:3000/api/xxx
            '/api': 'http://localhost:3000',

            // 將本地 /api2/xxx 代理到 localhost:3000/xxx
            '/api2': {
                target: 'http://localhost:3000',
                pathRewrite: {
                    '/api2': ''
                }
            }
        }
    }
})
  1. webpack.prod.js
const path = require('path')
const webpack = require('webpack')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const webpackCommonConf = require('./webpack.common.js')
const { smart } = require('webpack-merge')
const { srcPath, distPath } = require('./paths')

module.exports = smart(webpackCommonConf, {
    mode: 'production',
    output: {
        filename: 'bundle.[contentHash:8].js',  // 打包代碼時(shí),加上 hash 戳
        path: distPath,
        // publicPath: 'http://cdn.abc.com'  // 修改所有靜態(tài)文件 url 的前綴(如 cdn 域名),這里暫時(shí)用不到
    },
    module: {
        rules: [
            // 圖片 - 考慮 base64 編碼的情況
            {
                test: /\.(png|jpg|jpeg|gif)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        // 小于 5kb 的圖片用 base64 格式產(chǎn)出
                        // 否則,依然延用 file-loader 的形式,產(chǎn)出 url 格式
                        limit: 5 * 1024,

                        // 打包到 img 目錄下
                        outputPath: '/img1/',

                        // 設(shè)置圖片的 cdn 地址(也可以統(tǒng)一在外面的 output 中設(shè)置,那將作用于所有靜態(tài)資源)
                        // publicPath: 'http://cdn.abc.com'
                    }
                }
            },
        ]
    },
    plugins: [
        new CleanWebpackPlugin(), // 會(huì)默認(rèn)清空 output.path 文件夾
        new webpack.DefinePlugin({
            // window.ENV = 'production'
            ENV: JSON.stringify('production')
        })
    ]
})

二、 webpack 高級配置
  1. 多入口(公共配置中)
  2. webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { srcPath, distPath } = require('./paths')

module.exports = {
    entry: {
        index: path.join(srcPath, 'index.js'),
        other: path.join(srcPath, 'other.js')
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: ['babel-loader'],
                include: srcPath,
                exclude: /node_modules/
            },
            // {
            //     test: /\.css$/,
            //     // loader 的執(zhí)行順序是:從后往前
            //     loader: ['style-loader', 'css-loader']
            // },
            {
                test: /\.css$/,
                // loader 的執(zhí)行順序是:從后往前
                loader: ['style-loader', 'css-loader', 'postcss-loader'] // 加了 postcss
            },
            {
                test: /\.less$/,
                // 增加 'less-loader' ,注意順序
                loader: ['style-loader', 'css-loader', 'less-loader']
            }
        ]
    },
    plugins: [
        // new HtmlWebpackPlugin({
        //     template: path.join(srcPath, 'index.html'),
        //     filename: 'index.html'
        // })

        // 多入口 - 生成 index.html
        new HtmlWebpackPlugin({
            template: path.join(srcPath, 'index.html'),
            filename: 'index.html',
            // chunks 表示該頁面要引用哪些 chunk (即上面的 index 和 other),默認(rèn)全部引用
            chunks: ['index']  // 只引用 index.js
        }),
        // 多入口 - 生成 other.html
        new HtmlWebpackPlugin({
            template: path.join(srcPath, 'other.html'),
            filename: 'other.html',
            chunks: ['other']  // 只引用 other.js
        })
    ]
}

  1. 抽離和壓縮 css(優(yōu)化產(chǎn)出代碼)
    webpack.prod.js
const path = require('path')
const webpack = require('webpack')
const { smart } = require('webpack-merge')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const TerserJSPlugin = require('terser-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const webpackCommonConf = require('./webpack.common.js')
const { srcPath, distPath } = require('./paths')

module.exports = smart(webpackCommonConf, {
    mode: 'production',
    output: {
        // filename: 'bundle.[contentHash:8].js',  // 打包代碼時(shí),加上 hash 戳
        filename: '[name].[contentHash:8].js', // name 即多入口時(shí) entry 的 key
        path: distPath,
        // publicPath: 'http://cdn.abc.com'  // 修改所有靜態(tài)文件 url 的前綴(如 cdn 域名),這里暫時(shí)用不到
    },
    module: {
        rules: [
            // 圖片 - 考慮 base64 編碼的情況
            {
                test: /\.(png|jpg|jpeg|gif)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        // 小于 5kb 的圖片用 base64 格式產(chǎn)出
                        // 否則,依然延用 file-loader 的形式,產(chǎn)出 url 格式
                        limit: 5 * 1024,

                        // 打包到 img 目錄下
                        outputPath: '/img1/',

                        // 設(shè)置圖片的 cdn 地址(也可以統(tǒng)一在外面的 output 中設(shè)置,那將作用于所有靜態(tài)資源)
                        // publicPath: 'http://cdn.abc.com'
                    }
                }
            },
            // 抽離 css
            {
                test: /\.css$/,
                loader: [
                    MiniCssExtractPlugin.loader,  // 注意,這里不再用 style-loader
                    'css-loader',
                    'postcss-loader'
                ]
            },
            // 抽離 less --> css
            {
                test: /\.less$/,
                loader: [
                    MiniCssExtractPlugin.loader,  // 注意,這里不再用 style-loader
                    'css-loader',
                    'less-loader',
                    'postcss-loader'
                ]
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin(), // 會(huì)默認(rèn)清空 output.path 文件夾
        new webpack.DefinePlugin({
            // window.ENV = 'production'
            ENV: JSON.stringify('production')
        }),

        // 抽離 css 文件
        new MiniCssExtractPlugin({
            filename: 'css/main.[contentHash:8].css'
        })
    ],

    optimization: {
        // 壓縮 css
        minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
    }
})

  1. 抽離公共代碼和第三方代碼(優(yōu)化產(chǎn)出代碼)
    webpack.common.js(引入不同的 chunk)
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { srcPath, distPath } = require('./paths')

module.exports = {
    entry: {
        index: path.join(srcPath, 'index.js'),
        other: path.join(srcPath, 'other.js')
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: ['babel-loader'],
                include: srcPath,
                exclude: /node_modules/
            }
        ]
    },
    plugins: [
        // new HtmlWebpackPlugin({
        //     template: path.join(srcPath, 'index.html'),
        //     filename: 'index.html'
        // })

        // 多入口 - 生成 index.html
        new HtmlWebpackPlugin({
            template: path.join(srcPath, 'index.html'),
            filename: 'index.html',
            // chunks 表示該頁面要引用哪些 chunk (即上面的 index 和 other),默認(rèn)全部引用
            chunks: ['index', 'vendor', 'common']  // 要考慮代碼分割
        }),
        // 多入口 - 生成 other.html
        new HtmlWebpackPlugin({
            template: path.join(srcPath, 'other.html'),
            filename: 'other.html',
            chunks: ['other', 'common']  // 考慮代碼分割
        })
    ]
}

webpack.prod.js

const path = require('path')
const webpack = require('webpack')
const { smart } = require('webpack-merge')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const TerserJSPlugin = require('terser-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const webpackCommonConf = require('./webpack.common.js')
const { srcPath, distPath } = require('./paths')

module.exports = smart(webpackCommonConf, {
    mode: 'production',
    output: {
        // filename: 'bundle.[contentHash:8].js',  // 打包代碼時(shí),加上 hash 戳
        filename: '[name].[contentHash:8].js', // name 即多入口時(shí) entry 的 key
        path: distPath,
        // publicPath: 'http://cdn.abc.com'  // 修改所有靜態(tài)文件 url 的前綴(如 cdn 域名),這里暫時(shí)用不到
    },
    module: {
        rules: [
            // 圖片 - 考慮 base64 編碼的情況
            {
                test: /\.(png|jpg|jpeg|gif)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        // 小于 5kb 的圖片用 base64 格式產(chǎn)出
                        // 否則,依然延用 file-loader 的形式,產(chǎn)出 url 格式
                        limit: 5 * 1024,

                        // 打包到 img 目錄下
                        outputPath: '/img1/',

                        // 設(shè)置圖片的 cdn 地址(也可以統(tǒng)一在外面的 output 中設(shè)置,那將作用于所有靜態(tài)資源)
                        // publicPath: 'http://cdn.abc.com'
                    }
                }
            },
            // 抽離 css
            {
                test: /\.css$/,
                loader: [
                    MiniCssExtractPlugin.loader,  // 注意,這里不再用 style-loader
                    'css-loader',
                    'postcss-loader'
                ]
            },
            // 抽離 less
            {
                test: /\.less$/,
                loader: [
                    MiniCssExtractPlugin.loader,  // 注意,這里不再用 style-loader
                    'css-loader',
                    'less-loader',
                    'postcss-loader'
                ]
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin(), // 會(huì)默認(rèn)清空 output.path 文件夾
        new webpack.DefinePlugin({
            // window.ENV = 'production'
            ENV: JSON.stringify('production')
        }),

        // 抽離 css 文件
        new MiniCssExtractPlugin({
            filename: 'css/main.[contentHash:8].css'
        })
    ],

    optimization: {
        // 壓縮 css
        minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],

        // 分割代碼塊
        splitChunks: {
            chunks: 'all',
            /**
             * initial 入口 chunk,對于異步導(dǎo)入的文件不處理
                async 異步 chunk,只對異步導(dǎo)入的文件處理
                all 全部 chunk
             */

            // 緩存分組
            cacheGroups: {
                // 第三方模塊
                vendor: {
                    name: 'vendor', // chunk 名稱
                    priority: 1, // 權(quán)限更高,優(yōu)先抽離,重要?。?!優(yōu)先打包到哪個(gè)模塊
                    test: /node_modules/,  // 哪些內(nèi)容被打包到 vendor
                    minSize: 0,  // 大小限制
                    minChunks: 1  // 最少復(fù)用過幾次
                },

                // 公共的模塊
                common: {
                    name: 'common', // chunk 名稱
                    priority: 0, // 優(yōu)先級
                    minSize: 0,  // 公共模塊的大小限制
                    minChunks: 2  // 公共模塊最少復(fù)用過幾次
                }
            }
        }
    }
})
  1. 如何異步加載 js (懶加載)
setTimeOut(()=> {
    import ('./dynamic-data.js').then(res => {
})
}, 1500)  // 會(huì)產(chǎn)生一個(gè)單獨(dú)的 chunk
  1. 處理 JSX 安裝 @babal/preset-react
    babelrc
{
    "presets": ["@babal/preset-react"],
    "plugins": []
}
  1. 處理 JSX 安裝 vue-loader
    webpack.common.js
     {
            test: /\.vue$/,
            loader: ['vue-loader'],
            include: srcPath
     }
  1. module chunk bundle
module- webpack 中一切皆模塊
chunk- 多模塊的合成  如 entry import() splitChunk
bundle- 最終輸出的文件
image.png
三、webpack性能優(yōu)化
  1. 優(yōu)化打包構(gòu)建速度-開發(fā)體驗(yàn)和效率
  2. 優(yōu)化產(chǎn)出代碼-產(chǎn)品性能
    3.1


    image.png

3.1.2 happyPack 多進(jìn)程打包


image.png

3.1.3 ParallelUglifyPlugin 多進(jìn)程壓縮js


image.png

總結(jié): 根據(jù)項(xiàng)目實(shí)際情況判斷是否需要開啟多進(jìn)程打包和壓縮

image.png

代碼展示
webpack.prod.js

const path = require('path')
const webpack = require('webpack')
const { smart } = require('webpack-merge')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const TerserJSPlugin = require('terser-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const HappyPack = require('happypack')
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')
const webpackCommonConf = require('./webpack.common.js')
const { srcPath, distPath } = require('./paths')

module.exports = smart(webpackCommonConf, {
    mode: 'production',
    output: {
        // filename: 'bundle.[contentHash:8].js',  // 打包代碼時(shí),加上 hash 戳
        filename: '[name].[contentHash:8].js', // name 即多入口時(shí) entry 的 key
        path: distPath,
        // publicPath: 'http://cdn.abc.com'  // 修改所有靜態(tài)文件 url 的前綴(如 cdn 域名),這里暫時(shí)用不到
    },
    module: {
        rules: [
            // js
            {
                test: /\.js$/,
                // 把對 .js 文件的處理轉(zhuǎn)交給 id 為 babel 的 HappyPack 實(shí)例
                use: ['happypack/loader?id=babel'],
                include: srcPath,
                // exclude: /node_modules/
            },
            // 圖片 - 考慮 base64 編碼的情況
            {
                test: /\.(png|jpg|jpeg|gif)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        // 小于 5kb 的圖片用 base64 格式產(chǎn)出
                        // 否則,依然延用 file-loader 的形式,產(chǎn)出 url 格式
                        limit: 5 * 1024,

                        // 打包到 img 目錄下
                        outputPath: '/img1/',

                        // 設(shè)置圖片的 cdn 地址(也可以統(tǒng)一在外面的 output 中設(shè)置,那將作用于所有靜態(tài)資源)
                        // publicPath: 'http://cdn.abc.com'
                    }
                }
            },
            // 抽離 css
            {
                test: /\.css$/,
                loader: [
                    MiniCssExtractPlugin.loader,  // 注意,這里不再用 style-loader
                    'css-loader',
                    'postcss-loader'
                ]
            },
            // 抽離 less
            {
                test: /\.less$/,
                loader: [
                    MiniCssExtractPlugin.loader,  // 注意,這里不再用 style-loader
                    'css-loader',
                    'less-loader',
                    'postcss-loader'
                ]
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin(), // 會(huì)默認(rèn)清空 output.path 文件夾
        new webpack.DefinePlugin({
            // window.ENV = 'production'
            ENV: JSON.stringify('production')
        }),

        // 抽離 css 文件
        new MiniCssExtractPlugin({
            filename: 'css/main.[contentHash:8].css'
        }),

        // 忽略 moment 下的 /locale 目錄
        new webpack.IgnorePlugin(/\.\/locale/, /moment/),

        // happyPack 開啟多進(jìn)程打包
        new HappyPack({
            // 用唯一的標(biāo)識符 id 來代表當(dāng)前的 HappyPack 是用來處理一類特定的文件
            id: 'babel',
            // 如何處理 .js 文件,用法和 Loader 配置中一樣
            loaders: ['babel-loader?cacheDirectory']
        }),

        // 使用 ParallelUglifyPlugin 并行壓縮輸出的 JS 代碼
        new ParallelUglifyPlugin({
            // 傳遞給 UglifyJS 的參數(shù)
            // (還是使用 UglifyJS 壓縮,只不過幫助開啟了多進(jìn)程)
            uglifyJS: {
                output: {
                    beautify: false, // 最緊湊的輸出
                    comments: false, // 刪除所有的注釋
                },
                compress: {
                    // 刪除所有的 `console` 語句,可以兼容ie瀏覽器
                    drop_console: true,
                    // 內(nèi)嵌定義了但是只用到一次的變量
                    collapse_vars: true,
                    // 提取出出現(xiàn)多次但是沒有定義成變量去引用的靜態(tài)值
                    reduce_vars: true,
                }
            }
        })
    ],

    optimization: {
        // 壓縮 css
        minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],

        // 分割代碼塊
        splitChunks: {
            chunks: 'all',
            /**
             * initial 入口chunk,對于異步導(dǎo)入的文件不處理
                async 異步chunk,只對異步導(dǎo)入的文件處理
                all 全部chunk
             */

            // 緩存分組
            cacheGroups: {
                // 第三方模塊
                vendor: {
                    name: 'vendor', // chunk 名稱
                    priority: 1, // 權(quán)限更高,優(yōu)先抽離,重要!??!
                    test: /node_modules/,
                    minSize: 0,  // 大小限制
                    minChunks: 1  // 最少復(fù)用過幾次
                },

                // 公共的模塊
                common: {
                    name: 'common', // chunk 名稱
                    priority: 0, // 優(yōu)先級
                    minSize: 0,  // 公共模塊的大小限制
                    minChunks: 2  // 公共模塊最少復(fù)用過幾次
                }
            }
        }
    }
})

3.1.4 自動(dòng)刷新(知道即可,一般無需手動(dòng)配置)

  • 只有開發(fā)環(huán)境下有 自動(dòng)刷新(代碼改完之后,自動(dòng)更新)
  • 只要引入了 devServer 之后,會(huì)自動(dòng)開啟自動(dòng)刷新


    image.png
image.png

3.1.5 熱更新


image.png
const path = require('path')
const webpack = require('webpack')
const webpackCommonConf = require('./webpack.common.js')
const { smart } = require('webpack-merge')
const { srcPath, distPath } = require('./paths')
const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin');

module.exports = smart(webpackCommonConf, {
    mode: 'development',
    entry: {
        // index: path.join(srcPath, 'index.js'),
        index: [
            'webpack-dev-server/client?http://localhost:8080/',
            'webpack/hot/dev-server',
            path.join(srcPath, 'index.js')
        ],
        other: path.join(srcPath, 'other.js')
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: ['babel-loader?cacheDirectory'],
                include: srcPath,
                // exclude: /node_modules/
            },
            // 直接引入圖片 url
            {
                test: /\.(png|jpg|jpeg|gif)$/,
                use: 'file-loader'
            },
            // {
            //     test: /\.css$/,
            //     // loader 的執(zhí)行順序是:從后往前
            //     loader: ['style-loader', 'css-loader']
            // },
            {
                test: /\.css$/,
                // loader 的執(zhí)行順序是:從后往前
                loader: ['style-loader', 'css-loader', 'postcss-loader'] // 加了 postcss
            },
            {
                test: /\.less$/,
                // 增加 'less-loader' ,注意順序
                loader: ['style-loader', 'css-loader', 'less-loader']
            }
        ]
    },
    plugins: [
        new webpack.DefinePlugin({
            // window.ENV = 'production'
            ENV: JSON.stringify('development')
        }),
        new HotModuleReplacementPlugin()
    ],
    devServer: {
        port: 8080,
        progress: true,  // 顯示打包的進(jìn)度條
        contentBase: distPath,  // 根目錄
        open: true,  // 自動(dòng)打開瀏覽器
        compress: true,  // 啟動(dòng) gzip 壓縮

        hot: true,

        // 設(shè)置代理
        proxy: {
            // 將本地 /api/xxx 代理到 localhost:3000/api/xxx
            '/api': 'http://localhost:3000',

            // 將本地 /api2/xxx 代理到 localhost:3000/xxx
            '/api2': {
                target: 'http://localhost:3000',
                pathRewrite: {
                    '/api2': ''
                }
            }
        }
    },
    // watch: true, // 開啟監(jiān)聽,默認(rèn)為 false
    // watchOptions: {
    //     ignored: /node_modules/, // 忽略哪些
    //     // 監(jiān)聽到變化發(fā)生后會(huì)等300ms再去執(zhí)行動(dòng)作,防止文件更新太快導(dǎo)致重新編譯頻率太高
    //     // 默認(rèn)為 300ms
    //     aggregateTimeout: 300,
    //     // 判斷文件是否發(fā)生變化是通過不停的去詢問系統(tǒng)指定文件有沒有變化實(shí)現(xiàn)的
    //     // 默認(rèn)每隔1000毫秒詢問一次
    //     poll: 1000
    // }
})

style 修改可以直接生效,但是js 代碼需要增加配置
index.js

// // 增加,開啟熱更新之后的代碼邏輯
if (module.hot) {
   module.hot.accept(['./math'], () => {
     const sumRes = sum(10, 30)
     console.log('sumRes in hot', sumRes)    
   })
 }

總結(jié): 熱更新是有成本的,需要我們在開發(fā)環(huán)境下自己配置監(jiān)聽的模塊;

3.1.6 何時(shí)使用DllPlugin?(動(dòng)態(tài)鏈接庫)開發(fā)環(huán)境


image.png

image.png

webpack.dll.js

const path = require('path')
const DllPlugin = require('webpack/lib/DllPlugin')
const { srcPath, distPath } = require('./paths')

module.exports = {
  mode: 'development',
  // JS 執(zhí)行入口文件
  entry: {
    // 把 React 相關(guān)模塊的放到一個(gè)單獨(dú)的動(dòng)態(tài)鏈接庫
    react: ['react', 'react-dom']
  },
  output: {
    // 輸出的動(dòng)態(tài)鏈接庫的文件名稱,[name] 代表當(dāng)前動(dòng)態(tài)鏈接庫的名稱,
    // 也就是 entry 中配置的 react 和 polyfill
    filename: '[name].dll.js',
    // 輸出的文件都放到 dist 目錄下
    path: distPath,
    // 存放動(dòng)態(tài)鏈接庫的全局變量名稱,例如對應(yīng) react 來說就是 _dll_react
    // 之所以在前面加上 _dll_ 是為了防止全局變量沖突
    library: '_dll_[name]',
  },
  plugins: [
    // 接入 DllPlugin
    new DllPlugin({
      // 動(dòng)態(tài)鏈接庫的全局變量名稱,需要和 output.library 中保持一致
      // 該字段的值也就是輸出的 manifest.json 文件 中 name 字段的值
      // 例如 react.manifest.json 中就有 "name": "_dll_react"
      name: '_dll_[name]',
      // 描述動(dòng)態(tài)鏈接庫的 manifest.json 文件輸出時(shí)的文件名稱
      path: path.join(distPath, '[name].manifest.json'),
    }),
  ],
}
image.png

打包產(chǎn)出輸出預(yù)打包文件:


image.png

引用


image.png

webpack.dev.js
const path = require('path')
const webpack = require('webpack')
const { smart } = require('webpack-merge')
const webpackCommonConf = require('./webpack.common.js')
const { srcPath, distPath } = require('./paths')

// 第一,引入 DllReferencePlugin
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin');

module.exports = smart(webpackCommonConf, {
    mode: 'development',
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: ['babel-loader'],
                include: srcPath,
                exclude: /node_modules/ // 第二,不要再轉(zhuǎn)換 node_modules 的代碼
            },
        ]
    },
    plugins: [
        new webpack.DefinePlugin({
            // window.ENV = 'production'
            ENV: JSON.stringify('development')
        }),
        // 第三,告訴 Webpack 使用了哪些動(dòng)態(tài)鏈接庫
        new DllReferencePlugin({
            // 描述 react 動(dòng)態(tài)鏈接庫的文件內(nèi)容
            manifest: require(path.join(distPath, 'react.manifest.json')),
        }),
    ],
    devServer: {
        port: 8080,
        progress: true,  // 顯示打包的進(jìn)度條
        contentBase: distPath,  // 根目錄
        open: true,  // 自動(dòng)打開瀏覽器
        compress: true,  // 啟動(dòng) gzip 壓縮

        // 設(shè)置代理
        proxy: {
            // 將本地 /api/xxx 代理到 localhost:3000/api/xxx
            '/api': 'http://localhost:3000',

            // 將本地 /api2/xxx 代理到 localhost:3000/xxx
            '/api2': {
                target: 'http://localhost:3000',
                pathRewrite: {
                    '/api2': ''
                }
            }
        }
    }
})

總結(jié):

image.png
image.png

3.2 webpack 性能優(yōu)化-優(yōu)化產(chǎn)生代碼


image.png

3.2.1 小圖片 base64

    module: {
        rules: [
            // 圖片 - 考慮 base64 編碼的情況
            {
                test: /\.(png|jpg|jpeg|gif)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        // 小于 5kb 的圖片用 base64 格式產(chǎn)出
                        // 否則,依然延用 file-loader 的形式,產(chǎn)出 url 格式
                        limit: 5 * 1024,

                        // 打包到 img 目錄下
                        outputPath: '/img1/',

                        // 設(shè)置圖片的 cdn 地址(也可以統(tǒng)一在外面的 output 中設(shè)置,那將作用于所有靜態(tài)資源)
                        // publicPath: 'http://cdn.abc.com'
                    }
                }
            },
        ]
    },

3.2.2 contentHash

    output: {
        filename: 'bundle.[contentHash:8].js',  // 打包代碼時(shí),加上 hash 戳
        path: distPath,
        // publicPath: 'http://cdn.abc.com'  // 修改所有靜態(tài)文件 url 的前綴(如 cdn 域名),這里暫時(shí)用不到
    },

3.2.3 懶加載

  • import
    3.2.4 提取公共代碼
    splitChunks
    3.2.5 IngorePlugin
    打包體積會(huì)更小
    3.2.6 使用 cdn 加速
    output: {
        filename: 'bundle.[contentHash:8].js',  // 打包代碼時(shí),加上 hash 戳
        path: distPath,
        // publicPath: 'http://cdn.abc.com'  // 修改所有靜態(tài)文件 url 的前綴(如 cdn 域名),這里暫時(shí)用不到
    }

3.2.7 使用 production

mode: ‘production’
* 自動(dòng)開啟代碼壓縮
* Vue React 等會(huì)自動(dòng)刪掉調(diào)試代碼(如開發(fā)環(huán)境的 warning)
* 自動(dòng)啟用 Tree-Shaking

3.2.7.2 ES Module 和 Commonjs 的區(qū)別


image.png

3.2.7 使用 Scope Hosting(改變打包的作用域,打包更快,內(nèi)存占用更少)

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

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

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