webpack4.x配置詳解,多頁面,拆分代碼,多入口,多出口,新特性新坑!!

花了差很少一天多的時間,從新擼了一遍webpack4.x的經常使用配置。css

github詳細代碼地址,若有幫助,請賜我一顆小星星。 https://github.com/pomelott/webpack4.x_Demo html

基本上經常使用的配置都熟悉了一遍,整體上來說,爲了對parcel進行反擊,webpack從4.x開始,正在朝着儘量的簡化配置文件的方向發展。node

1、首先來看下,webpack4的新特性。jquery

1.webpack不在單獨使用,4.x版本將不少命令移動到了webpack-cli包中。若想要本地安裝使用webpack,通常須要如下兩步webpack

(1)全局安裝webpack,webpack-cligit

(2)局部安裝webpack,weback-cligithub

2.增長了模式區分(development,production):web

開發者可經過webpack --mode development/production   進行模式切換,也能夠經過在配置文件中添加mode配置項進行模式選擇。json

development:開發模式,打包默認不壓縮代碼,默認開啓代碼調試瀏覽器

production:生產模式,上線時使用,打包壓縮代碼,不開啓代碼調試。

***若要開啓代碼調試可在配置文件中增長devtool配置項

devtool: "source-map"

3.固定入口目錄爲src,與入口默認文件index.js(webpack4.x向簡化配置方向發展的第一步)。

當只有src目錄與src目錄下的index.js時,無需增長webpack.config.js,4.x版本也會將打包後文件放至新增的dist目錄下。

4. js代碼抽離時,需在config中新增optimization配置項(下面會詳細說拆分代碼的規則)

  optimization: {
        splitChunks: {
            cacheGroups: {
                vendor: {
                    chunks: "initial",
                    name: "jquery",
                    enforce: true
                }
            }
        }
    }

2、4.x版本我的習慣的項目目錄結構以下圖,整個目錄徹底爲動手搭建,並不是用腳手架修改而成。

3、配置文件核心要點

(1)當項目須要多文件入口時,入口項須要以json的格式添加

    entry: {
        // 多入口文件
        a: './src/js/index.js',
        b: './src/js/index2.js',
        jquery: 'jquery'
    }

(2)當多入口文件對應多出口文件時,出口文件的name須要與入口項的key相對應

    output: {
        path:path.resolve(__dirname, 'dist'),
        // 打包多出口文件
        // 生成 a.bundle.js  b.bundle.js  jquery.bundle.js
        filename: './js/[name].bundle.js'
    }

(3)多html文件須要new多個htmlWebpackPlugin實例

         // 自動生成html模板
        new htmlWebpackPlugin({
            filename: "index.html",
            title: "xxxx",
            chunks: ['a',"jquery"],  // 按需引入對應名字的js文件
            template: "./src/index.html"
        }),
        new htmlWebpackPlugin({
            chunks: ['b'],
            filename: "index2.html",
            title: "page2",
            template: "./src/index2.html"
        })

(4)按依賴提取js時,4.x版本寫法與以前徹底不一樣

    // 提取js,lib1名字可改
    optimization: {
        splitChunks: {
            cacheGroups: {
                lib1: {
                    chunks: "initial",
                    name: "jquery",
                    enforce: true
                }
            }
        }
    }

在多頁使用webpack時,其實咱們最頭疼的或者需求最大的就是代碼拆分問題。代碼是否拆分,怎麼拆,什麼狀況下拆。最新的splitChunksPlugin基本能知足咱們的全部需求。

我在  webpack4.x版本splitChunksPlugin的配置項詳解與實際應用場景  中提到過,最重要的就是priority這個屬性。下面具體說下咱們的實際須要:

首先須要肯定的是你是想優先匹配本身定義的拆分規則仍是想優先匹配webpack默認的拆分規則,若相匹配本身定義的拆分規則,則priority須要設置爲正數,優先匹配默認拆分規則就設置爲負數。

最終webpack會根據優先級進行打包(從大到小,從正數到負數)。

(5)引入第三方庫時,建議全局暴露。這樣在打包時,4.x會按需打包。

        // 全局暴露統一入口,其餘文件直接用就能夠
        new webpack.ProvidePlugin({
            $: "jquery"
        }),

4、下面附上三個主要的配置文件

1.webpack.config.js

const path = require('path');
const pluginsConfig = require("./webpack.plguins.js");
const rulesConfig = require("./webpack.rules.js");

module.exports = {
    entry: {
        // 多入口文件
        a: './src/js/index.js',
        b: './src/js/index2.js',
        jquery: 'jquery'
    },
    output: {
        path:path.resolve(__dirname, 'dist'),
        // 打包多出口文件
        // 生成 a.bundle.js  b.bundle.js  jquery.bundle.js
        filename: './js/[name].bundle.js'
    },
    plugins: pluginsConfig,
    devServer: {
        contentBase: path.resolve(__dirname, "dist"),
        host: "localhost",
        port: "8090",
        open: true, // 開啓瀏覽器
        hot: true   // 開啓熱更新
    },
    // devtool: "source-map",  // 開啓調試模式
    module:{
        rules: rulesConfig
    },
    // 提取js,lib1名字可改
    optimization: {
        splitChunks: {
            cacheGroups: {
                lib1: {
                    chunks: "initial",
                    name: "jquery",
                    enforce: true
                }
            }
        }
    }

}

2.webpack.plugins.js

const webpack = require("webpack");
const path = require('path');
const glob = require("glob");
//消除冗餘的css
const purifyCssWebpack = require("purifycss-webpack");
// html模板
const htmlWebpackPlugin = require("html-webpack-plugin");
// 清除目錄等
const cleanWebpackPlugin = require("clean-webpack-plugin");
//4.x以前用以壓縮
const uglifyjsWebpackPlugin = require("uglifyjs-webpack-plugin");
// 分離css
const extractTextPlugin = require("extract-text-webpack-plugin");
//靜態資源輸出
const copyWebpackPlugin = require("copy-webpack-plugin");
module.exports = [
        new webpack.HotModuleReplacementPlugin(),
        // 調用以前先清除
        new cleanWebpackPlugin(["dist"]),
        // 4.x以前可用uglifyjs-webpack-plugin用以壓縮文件,4.x可用--mode更改模式爲production來壓縮文件
        // new uglifyjsWebpackPlugin(),
        new copyWebpackPlugin([{
            from: path.resolve(__dirname,"src/assets"),
            to: './pulic'
        }]),
        // 分離css插件參數爲提取出去的路徑
        new extractTextPlugin("css/index.css"),
        // 消除冗餘的css代碼
        new purifyCssWebpack({
            // glob爲掃描模塊,使用其同步方法
            paths: glob.sync(path.join(__dirname, "src/*.html"))
        }),
        // 全局暴露統一入口
        new webpack.ProvidePlugin({
            $: "jquery"
        }),
        // 自動生成html模板
        new htmlWebpackPlugin({
            filename: "index.html",
            title: "xxxx",
            chunks: ['a',"jquery"],  // 按需引入對應名字的js文件
            template: "./src/index.html"
        }),
        new htmlWebpackPlugin({
            chunks: ['b'],
            filename: "index2.html",
            title: "page2",
            template: "./src/index2.html"
        })
]

3.webpack.rules.js

const extractTextPlugin = require("extract-text-webpack-plugin");
module.exports = [
            {
                test: /\.css$/,
                // 不分離的寫法
                // use: ["style-loader", "css-loader"]
                // 使用postcss不分離的寫法
                // use: ["style-loader", "css-loader", "postcss-loader"]
                // 此處爲分離css的寫法
                /*use: extractTextPlugin.extract({
                    fallback: "style-loader",
                    use: "css-loader",
                    // css中的基礎路徑
                    publicPath: "../"

                })*/
                // 此處爲使用postcss分離css的寫法
                use: extractTextPlugin.extract({
                    fallback: "style-loader",
                    use: ["css-loader", "postcss-loader"],
                    // css中的基礎路徑
                    publicPath: "../"

                })
            },
            {
                test: /\.js$/,
                use: ["babel-loader"],
                // 不檢查node_modules下的js文件
                exclude: "/node_modules/"
            },
            {
                test: /\.(png|jpg|gif)$/,
                use: [{
                        // 須要下載file-loader和url-loader
                        loader: "url-loader",
                        options: {
                            limit: 50,
                            // 圖片文件輸出的文件夾
                            outputPath: "images"
                        }
                    }
                ]
            },
            {
                test: /\.html$/,
                // html中的img標籤
                use: ["html-withimg-loader"]
            },
            {
                test: /\.less$/,
                // 三個loader的順序不能變
                // 不分離的寫法
                // use: ["style-loader", "css-loader", "less-loader"]
                // 分離的寫法
                use: extractTextPlugin.extract({
                    fallback:"style-loader",
                    use: ["css-loader", "less-loader"]
                })
            },
            {
                test: /\.(scss|sass)$/,
                // sass不分離的寫法,順序不能變
                // use: ["style-loader", "css-loader", "sass-loader"]
                // 分離的寫法
                use: extractTextPlugin.extract({
                    fallback:"style-loader",
                    use: ["css-loader", "sass-loader"]
                })
            }
        ]

***習慣用webpack以後,會很方便。不要怕出問題,解決問題後的成就感會讓你更增強大。github上有本次4.x版本的demo,歡迎小夥伴提問題,若是以爲還不錯,請給星!!

相關文章
相關標籤/搜索