亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

為什么我們要做三份 Webpack 配置文件

silencezwm / 534人閱讀

摘要:時(shí)至今日,已經(jīng)成為前端工程必備的基礎(chǔ)工具之一,不僅被廣泛用于前端工程發(fā)布前的打包,還在開發(fā)中擔(dān)當(dāng)本地前端資源服務(wù)器模塊熱更新等角色,結(jié)合等代碼檢查工具,還可以實(shí)現(xiàn)在對(duì)源代碼的嚴(yán)格校驗(yàn)檢查。

時(shí)至今日,Webpack 已經(jīng)成為前端工程必備的基礎(chǔ)工具之一,不僅被廣泛用于前端工程發(fā)布前的打包,還在開發(fā)中擔(dān)當(dāng)本地前端資源服務(wù)器(assets server)、模塊熱更新(hot module replacement)、API Proxy 等角色,結(jié)合 ESLint 等代碼檢查工具,還可以實(shí)現(xiàn)在對(duì)源代碼的嚴(yán)格校驗(yàn)檢查。

正如上文中提到的,前端從開發(fā)到部署前都離不開 Webpack 的參與,而 Webpack 的默認(rèn)配置文件只有一個(gè),即 webpack.config.js,那么問題來了,開發(fā)期和部署前應(yīng)該使用同一份 Webpack 配置嗎?答案肯定是否定的,既然 webpack.config.js 是一個(gè) JS 文件,我們當(dāng)然可以在文件里寫 JavaScript 業(yè)務(wù)邏輯,通過讀取環(huán)境變量 NODE_ENV 來判斷當(dāng)前是在開發(fā)(dev)時(shí)還是最終的生產(chǎn)環(huán)境(production),然而很多同學(xué)習(xí)慣把這兩者的配置都混寫在根目錄下的 webpack.config.js,通過很多零散的 if…else 來“臨時(shí)”決定某一個(gè) plugin 或者某一個(gè) loader 的配置項(xiàng),隨著 loaders 和 plugins 的不斷增加,久而久之 webpack.config.js 變得原來越隆長(zhǎng),代碼的可讀性和可維護(hù)性也大大下降。

我想通過本文來介紹一種用 3 個(gè) JS 文件來配置 Webpack 的方法,這里借鑒了很多開源項(xiàng)目的配置,同時(shí)也結(jié)合了我們自己在開發(fā)中碰到的種種問題解決方案。

本文中提及的配置基于 Webpack 2 或以上,建議使用 3.0 及以上版本

開發(fā)環(huán)境與生產(chǎn)環(huán)境的區(qū)別

  • 開發(fā)環(huán)境

    NODE_ENV 為 development
    啟用模塊熱更新(hot module replacement)
    額外的 webpack-dev-server 配置項(xiàng),API Proxy 配置項(xiàng)
    輸出 Sourcemap

  • 生產(chǎn)環(huán)境

    NODE_ENV 為 production
    將 React、jQuery 等常用庫(kù)設(shè)置為 external,直接采用 CDN 線上的版本
    樣式源文件(如 css、less、scss 等)需要通過 ExtractTextPlugin 獨(dú)立抽取成 css 文件
    啟用 post-css
    啟用 optimize-minimize(如 uglify 等)
    中大型的商業(yè)網(wǎng)站生產(chǎn)環(huán)境下,是絕對(duì)不能有 console.log() 的,所以要為 babel 配置 Remove console transform

    這里需要說明的是因?yàn)殚_發(fā)環(huán)境下啟用了 hot module replacement,為了讓樣式源文件的修改也同樣能被熱替換,不能使用 ExtractTextPlugin,而轉(zhuǎn)為隨 JS Bundle 一起輸出。

你需要三份配置文件

  1. webpack.base.config.js
    在 base 文件里,你需要將開發(fā)環(huán)境和生產(chǎn)環(huán)境中通用的配置集中放在這里:

    const CleanWebpackPlugin = require("clean-webpack-plugin");
    const path = require("path");
    const webpack = require("webpack");

    // 配置常量
    // 源代碼的根目錄(本地物理文件路徑)
    const SRC_PATH = path.resolve("./src");
    // 打包后的資源根目錄(本地物理文件路徑)
    const ASSETS_BUILD_PATH = path.resolve("./build");
    // 資源根目錄(可以是 CDN 上的絕對(duì)路徑,或相對(duì)路徑)
    const ASSETS_PUBLIC_PATH = "/assets/";

    module.exports = {
    context: SRC_PATH, // 設(shè)置源代碼的默認(rèn)根路徑
    resolve: {
        extensions: [".js", ".jsx"]  // 同時(shí)支持 js 和 jsx
    },
    entry: {
        // 注意 entry 中的路徑都是相對(duì)于 SRC_PATH 的路徑
        vendor: "./vendor",
        a: ["./entry-a"],
        b: ["./entry-b"],
        c: ["./entry-c"]
    },
    output: {
        path: ASSETS_BUILD_PATH,
        publicPath: ASSETS_PUBLIC_PATH,
        filename: "./[name].js"
    },
    module: {
        rules: [
        {
            enforce: "pre",  // ESLint 優(yōu)先級(jí)高于其他 JS 相關(guān)的 loader
            test: /.jsx?$/,
            exclude: /node_modules/,
            loader: "eslint-loader"
        },
        {
            test: /.jsx?$/,
            exclude: /node_modules/,
            // 建議把 babel 的運(yùn)行時(shí)配置放在 .babelrc 里,從而與 eslint-loader 等共享配置
            loader: "babel-loader"
        },
        {
            test: /.(png|jpg|gif)$/,
            use:
            [
            {
                loader: "url-loader",
                options:
                {
                limit: 8192,
                name: "images/[name].[ext]"
                }
            }
            ]
        },
        {
            test: /.woff(2)?(?v=[0-9].[0-9].[0-9])?$/,
            use:
            [
            {
                loader: "url-loader",
                options:
                {
                limit: 8192,
                mimetype: "application/font-woff",
                name: "fonts/[name].[ext]"
                }
            }
            ]
        },
        {
            test: /.(ttf|eot|svg)(?v=[0-9].[0-9].[0-9])?$/,
            use:
            [
            {
                loader: "file-loader",
                options:
                {
                limit: 8192,
                mimetype: "application/font-woff",
                name: "fonts/[name].[ext]"
                }
            }
            ]
        }
        ]
    },
    plugins: [
        // 每次打包前,先清空原來目錄中的內(nèi)容
        new CleanWebpackPlugin([ASSETS_BUILD_PATH], { verbose: false }),
        // 啟用 CommonChunkPlugin
        new webpack.optimize.CommonsChunkPlugin({
        names: "vendor",
        minChunks: Infinity
        })
    ]
    };
  1. webpack.dev.config.js

    這是用于開發(fā)環(huán)境的 Webpack 配置,繼承自 base:

    const webpack = require("webpack");
    
    // 讀取同一目錄下的 base config
    const config = require("./webpack.base.config");
    
    // 添加 webpack-dev-server 相關(guān)的配置項(xiàng)
    config.devServer = {
    contentBase: "./",
    hot: true,
    publicPath: "/assets/"
    };
    // 有關(guān) Webpack 的 API 本地代理,另請(qǐng)參考 https://webpack.github.io/docs/webpack-dev-server.html#proxy
    
    config.module.rules.push(
    {
        test: /.less$/,
        use: [
        "style-loader",
        "css-loader",
        "less-loader"
        ],
        exclude: /node_modules/
    }
    );
    
    // 真實(shí)場(chǎng)景中,React、jQuery 等優(yōu)先走全站的 CDN,所以要放在 externals 中
    config.externals = {
    react: "React",
    "react-dom": "ReactDOM"
    };
    
    // 添加 Sourcemap 支持
    config.plugins.push(
    new webpack.SourceMapDevToolPlugin({
        filename: "[file].map",
        exclude: ["vendor.js"] // vendor 通常不需要 sourcemap
    })
    );
    
    // Hot module replacement
    Object.keys(config.entry).forEach((key) => {
    // 這里有一個(gè)私有的約定,如果 entry 是一個(gè)數(shù)組,則證明它需要被 hot module replace
    if (Array.isArray(config.entry[key])) {
        config.entry[key].unshift(
        "webpack-dev-server/client?http://0.0.0.0:8080",
        "webpack/hot/only-dev-server"
        );
    }
    });
    config.plugins.push(
    new webpack.HotModuleReplacementPlugin()
    );
    
    module.exports = config;
  1. webpack.config.js

    這是用于生產(chǎn)環(huán)境的 webpack 配置,同樣繼承自 base:

    const webpack = require("webpack");
    const ExtractTextPlugin = require("extract-text-webpack-plugin");
    
    // 讀取同一目錄下的 base config
    const config = require("./webpack.base.config");
    
    config.module.rules.push(
    {
        test: /.less$/,
        use: ExtractTextPlugin.extract(
        {
            use: [
            "css-loader",
            "less-loader"
            ],
            fallback: "style-loader"
        }
        ),
        exclude: /node_modules/
    }
    );
    
    config.plugins.push(
    // 官方文檔推薦使用下面的插件確保 NODE_ENV
    new webpack.DefinePlugin({
        "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "production")
    }),
    // 啟動(dòng) minify
    new webpack.LoaderOptionsPlugin({ minimize: true }),
    // 抽取 CSS 文件
    new ExtractTextPlugin({
        filename: "[name].css",
        allChunks: true,
        ignoreOrder: true
    })
    );
    
    module.exports = config;

現(xiàn)在在你的工程文件夾里應(yīng)該已經(jīng)有三個(gè) Webpack 配置文件,它們分別是:

webpack.base.config.js
webpack.dev.config.js
webpack.config.js

最后,你還需要在 package.json 里添加相應(yīng)的配置:


    {
    ...
    "scripts": {
        "build": "webpack --optimize-minimize",
        "dev": "webpack-dev-server --config webpack.dev.config.js",
        "start": "npm run dev" // 或添加你自己的 start 邏輯
    },
    ...
    }

和很多項(xiàng)目一樣,在開發(fā)環(huán)境下的時(shí)候,你需要使用 npm run dev 來啟動(dòng),而在生產(chǎn)環(huán)境中,則用 npm run build 來發(fā)布。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/2255.html

相關(guān)文章

  • 20170917 前端開發(fā)周報(bào):JavaScript函數(shù)式編程、作用域和閉包

    摘要:用函數(shù)式編程對(duì)進(jìn)行斷舍離當(dāng)從業(yè)的老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了的特性,也不用面向?qū)ο罅耍詈蟀l(fā)現(xiàn)了真愛啊作用域和閉包作用域和閉包在里非常重要。旨在幫助非函數(shù)式編程的同學(xué),能快速切入到函數(shù)式編程的理念。 1、用函數(shù)式編程對(duì)JavaScript進(jìn)行斷舍離 當(dāng)從業(yè)20的JavaScript老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了90%的特性,也不用面向?qū)ο罅?,最后發(fā)現(xiàn)了真愛?。。?! https:/...

    tomener 評(píng)論0 收藏0
  • 20170917 前端開發(fā)周報(bào):JavaScript函數(shù)式編程、作用域和閉包

    摘要:用函數(shù)式編程對(duì)進(jìn)行斷舍離當(dāng)從業(yè)的老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了的特性,也不用面向?qū)ο罅耍詈蟀l(fā)現(xiàn)了真愛啊作用域和閉包作用域和閉包在里非常重要。旨在幫助非函數(shù)式編程的同學(xué),能快速切入到函數(shù)式編程的理念。 1、用函數(shù)式編程對(duì)JavaScript進(jìn)行斷舍離 當(dāng)從業(yè)20的JavaScript老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了90%的特性,也不用面向?qū)ο罅耍詈蟀l(fā)現(xiàn)了真愛?。。?! https:/...

    cyixlq 評(píng)論0 收藏0
  • 20170917 前端開發(fā)周報(bào):JavaScript函數(shù)式編程、作用域和閉包

    摘要:用函數(shù)式編程對(duì)進(jìn)行斷舍離當(dāng)從業(yè)的老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了的特性,也不用面向?qū)ο罅?,最后發(fā)現(xiàn)了真愛啊作用域和閉包作用域和閉包在里非常重要。旨在幫助非函數(shù)式編程的同學(xué),能快速切入到函數(shù)式編程的理念。 1、用函數(shù)式編程對(duì)JavaScript進(jìn)行斷舍離 當(dāng)從業(yè)20的JavaScript老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了90%的特性,也不用面向?qū)ο罅?,最后發(fā)現(xiàn)了真愛啊?。?! https:/...

    lentoo 評(píng)論0 收藏0
  • 摒棄gulp.js+require.js,使用webpack配置多頁面web項(xiàng)目

    摘要:主要做了兩套方案,一套是基于的單頁應(yīng)用,還有一套就是多頁應(yīng)用。麻煩的是原先使用這個(gè)方案。這太麻煩了,還不如使用一步到位。后記暫時(shí)只做了這些,這套工具還沒有正式投入使用估計(jì)會(huì)有挺多問題的。 不想看下面廢話的,可以直接看這里。 前言 這兩周負(fù)責(zé)公司前端基礎(chǔ)工程的建設(shè)。主要做了兩套方案,一套是基于vue的單頁應(yīng)用,還有一套就是多頁應(yīng)用。對(duì)于vue單頁這塊是沒什么問題的,直接用vue-cli生...

    lingdududu 評(píng)論0 收藏0
  • 深入淺出webpack學(xué)習(xí)(11)--多種類型配置

    摘要:如果采用導(dǎo)出一個(gè)來描述所需配置的方法需要寫兩個(gè)文件。再在啟動(dòng)時(shí)通過指定使用哪個(gè)配置文件。例如啟動(dòng)命令是時(shí),則的值是。采用描述的一份配置采用函數(shù)描述的一份配置采用異步函數(shù)描述的一份配置以上配置會(huì)導(dǎo)致針對(duì)這三份配置執(zhí)行三次不同的構(gòu)建。 除了通過導(dǎo)出一個(gè)Object來描述webpack所需要的配置,還有其他更靈活的方式,以簡(jiǎn)化不同場(chǎng)景的配置。下面來一一介紹它們。 1. 導(dǎo)出一個(gè)Functio...

    idisfkj 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<