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í)行順序是:從后往前(知識點)
            //     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,  // 自動打開瀏覽器
        compress: true,  // 啟動 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',  // 打包代碼時普碎,加上 hash 戳
        path: distPath,
        // publicPath: 'http://cdn.abc.com'  // 修改所有靜態(tài)文件 url 的前綴(如 cdn 域名),這里暫時用不到
    },
    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(), // 會默認(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',  // 打包代碼時表箭,加上 hash 戳
        filename: '[name].[contentHash:8].js', // name 即多入口時 entry 的 key
        path: distPath,
        // publicPath: 'http://cdn.abc.com'  // 修改所有靜態(tài)文件 url 的前綴(如 cdn 域名)枣察,這里暫時用不到
    },
    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(), // 會默認(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',  // 打包代碼時握童,加上 hash 戳
        filename: '[name].[contentHash:8].js', // name 即多入口時 entry 的 key
        path: distPath,
        // publicPath: 'http://cdn.abc.com'  // 修改所有靜態(tài)文件 url 的前綴(如 cdn 域名)姆怪,這里暫時用不到
    },
    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(), // 會默認(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)先抽離揪胃,重要Aв础!喊递!優(yōu)先打包到哪個模塊
                    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)  // 會產(chǎn)生一個單獨的 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ā)體驗和效率
  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ù)項目實際情況判斷是否需要開啟多進(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',  // 打包代碼時,加上 hash 戳
        filename: '[name].[contentHash:8].js', // name 即多入口時 entry 的 key
        path: distPath,
        // publicPath: 'http://cdn.abc.com'  // 修改所有靜態(tài)文件 url 的前綴(如 cdn 域名)骚勘,這里暫時用不到
    },
    module: {
        rules: [
            // js
            {
                test: /\.js$/,
                // 把對 .js 文件的處理轉(zhuǎn)交給 id 為 babel 的 HappyPack 實例
                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(), // 會默認(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)先抽離株依,重要Gぁ!恋腕!
                    test: /node_modules/,
                    minSize: 0,  // 大小限制
                    minChunks: 1  // 最少復(fù)用過幾次
                },

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

3.1.4 自動刷新(知道即可抹锄,一般無需手動配置)

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


    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,  // 自動打開瀏覽器
        compress: true,  // 啟動 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ā)生后會等300ms再去執(zhí)行動作哈肖,防止文件更新太快導(dǎo)致重新編譯頻率太高
    //     // 默認(rèn)為 300ms
    //     aggregateTimeout: 300,
    //     // 判斷文件是否發(fā)生變化是通過不停的去詢問系統(tǒng)指定文件有沒有變化實現(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 何時使用DllPlugin摊趾?(動態(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)模塊的放到一個單獨的動態(tài)鏈接庫
    react: ['react', 'react-dom']
  },
  output: {
    // 輸出的動態(tài)鏈接庫的文件名稱,[name] 代表當(dāng)前動態(tài)鏈接庫的名稱游两,
    // 也就是 entry 中配置的 react 和 polyfill
    filename: '[name].dll.js',
    // 輸出的文件都放到 dist 目錄下
    path: distPath,
    // 存放動態(tài)鏈接庫的全局變量名稱砾层,例如對應(yīng) react 來說就是 _dll_react
    // 之所以在前面加上 _dll_ 是為了防止全局變量沖突
    library: '_dll_[name]',
  },
  plugins: [
    // 接入 DllPlugin
    new DllPlugin({
      // 動態(tài)鏈接庫的全局變量名稱,需要和 output.library 中保持一致
      // 該字段的值也就是輸出的 manifest.json 文件 中 name 字段的值
      // 例如 react.manifest.json 中就有 "name": "_dll_react"
      name: '_dll_[name]',
      // 描述動態(tài)鏈接庫的 manifest.json 文件輸出時的文件名稱
      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 使用了哪些動態(tài)鏈接庫
        new DllReferencePlugin({
            // 描述 react 動態(tài)鏈接庫的文件內(nèi)容
            manifest: require(path.join(distPath, 'react.manifest.json')),
        }),
    ],
    devServer: {
        port: 8080,
        progress: true,  // 顯示打包的進(jìn)度條
        contentBase: distPath,  // 根目錄
        open: true,  // 自動打開瀏覽器
        compress: true,  // 啟動 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',  // 打包代碼時肴沫,加上 hash 戳
        path: distPath,
        // publicPath: 'http://cdn.abc.com'  // 修改所有靜態(tài)文件 url 的前綴(如 cdn 域名)粟害,這里暫時用不到
    },

3.2.3 懶加載

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

3.2.7 使用 production

mode: ‘production’
* 自動開啟代碼壓縮
* Vue React 等會自動刪掉調(diào)試代碼(如開發(fā)環(huán)境的 warning)
* 自動啟用 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)系作者
  • 序言:七十年代末站蝠,一起剝皮案震驚了整個濱河市汰具,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌菱魔,老刑警劉巖智厌,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挡篓,死亡現(xiàn)場離奇詭異偎蘸,居然都是意外死亡篡殷,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門藻治,熙熙樓的掌柜王于貴愁眉苦臉地迎上來碘勉,“玉大人,你說我怎么就攤上這事桩卵⊙槊遥” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵雏节,是天一觀的道長胜嗓。 經(jīng)常有香客問我,道長钩乍,這世上最難降的妖魔是什么兼蕊? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮件蚕,結(jié)果婚禮上孙技,老公的妹妹穿的比我還像新娘。我一直安慰自己排作,他們只是感情好牵啦,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著妄痪,像睡著了一般哈雏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上衫生,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天裳瘪,我揣著相機(jī)與錄音,去河邊找鬼罪针。 笑死彭羹,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的泪酱。 我是一名探鬼主播派殷,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼墓阀!你這毒婦竟也來了毡惜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤斯撮,失蹤者是張志新(化名)和其女友劉穎经伙,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體勿锅,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡帕膜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了粱甫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泳叠。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖茶宵,靈堂內(nèi)的尸體忽然破棺而出危纫,到底是詐尸還是另有隱情,我是刑警寧澤乌庶,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布种蝶,位于F島的核電站,受9級特大地震影響瞒大,放射性物質(zhì)發(fā)生泄漏螃征。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一透敌、第九天 我趴在偏房一處隱蔽的房頂上張望盯滚。 院中可真熱鬧踢械,春花似錦、人聲如沸魄藕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽背率。三九已至话瞧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間寝姿,已是汗流浹背交排。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留饵筑,地道東北人埃篓。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像翻翩,于是被迫代替她去往敵國和親都许。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容