做者按:這是
webpack4
系列最後一篇教程了。這篇文章在以前全部教程的基礎上,作了一個真正意義上的 webpack 項目!我花費了三個月整理了這份教程,而且完善了相關示例代碼,也更熟悉 webpack 的理論和應用,固然,也感謝你們的支持。好了,感慨完畢,開始正題 👇javascript
本節課的代碼目錄以下:css
熟悉 Vuejs 或者 ReactJs 的腳手架的朋友應該都知道:在根目錄下有一個/build/
文件夾,專門放置webpack
配置文件的相關代碼。html
不像咱們前 15 節課的 demo (只有一個配置文件webpack.config.js
),爲了分離開發環境和生產環境,咱們須要分別編寫對應的webpack
配置代碼。vue
毫無疑問,有一些插件和配置是兩種環境共用的,因此應該提煉出來,避免重複勞動。如前文目錄截圖,build/webpack.common.conf.js
就保存了兩種環境都通用的配置文件。而build/webpack.dev.conf.js
和build/webpack.prod.conf.js
分別是開發和生產環境須要的特殊配置。java
package.json
相似上一節講的,爲了讓命令更好調用,須要配置scripts
選項。模仿vue-cli
的命令格式,編寫以下package.json
:node
{ "scripts": { "dev": "webpack-dev-server --env development --open --config build/webpack.common.conf.js", "build": "webpack --env production --config build/webpack.common.conf.js" }, "devDependencies": { "babel-core": "^6.26.3", "babel-loader": "^7.1.5", "babel-plugin-transform-runtime": "^6.23.0", "babel-preset-env": "^1.7.0", "clean-webpack-plugin": "^0.1.19", "css-loader": "^1.0.0", "extract-text-webpack-plugin": "^4.0.0-beta.0", "html-webpack-plugin": "^3.2.0", "jquery": "^3.3.1", "style-loader": "^0.21.0", "webpack": "^4.16.1", "webpack-cli": "^3.1.0", "webpack-dev-server": "^3.1.4", "webpack-merge": "^4.1.3" }, "dependencies": { "babel-polyfill": "^6.26.0", "babel-runtime": "^6.26.0" } }
按照配置,運行:jquery
npm run dev
: 進入開發調試模式npm run build
: 生成打包文件還能夠看出來,build/webpack.common.conf.js
不單單是存放着兩種環境的公共代碼,仍是webpack
命令的入口文件。webpack
根據前面所講,咱們有 3 個配置文件。那麼如何在build/webpack.common.conf.js
中引入開發或者生產環境的配置,而且正確合併呢?git
此時須要藉助webpack-merge
這個第三方庫。下面是個示例代碼:github
const merge = require("webpack-merge"); const productionConfig = require("./webpack.prod.conf"); const developmentConfig = require("./webpack.dev.conf"); const commonConfig = {}; // ... 省略 module.exports = env => { let config = env === "production" ? productionConfig : developmentConfig; return merge(commonConfig, config); // 合併 公共配置 和 環境配置 };
若是這個 js 文件是 webpack 命令的入口文件,例如build/webpack.common.conf.js
,那麼mode
的值(production 或者 development)會被自動傳入module.exports
的第一個參數,開發者能夠直接使用。
以下面的代碼,先判斷是什麼環境,而後再決定使用什麼配置,最後 return 給 webpack:
module.exports = env => { let config = env === "production" ? productionConfig : developmentConfig; return merge(commonConfig, config); // 合併 公共配置 和 環境配置 };
若是這個 js 文件是項目中的腳本文件,那麼能夠訪問process.env.NODE_ENV
這個變量來判斷環境:
if (process.env.NODE_ENV === "development") { console.log("開發環境"); } else { console.log("生產環境"); }
// /build/webpack.common.conf.js const webpack = require("webpack"); const merge = require("webpack-merge"); const ExtractTextPlugin = require("extract-text-webpack-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const path = require("path"); const productionConfig = require("./webpack.prod.conf.js"); // 引入生產環境配置文件 const developmentConfig = require("./webpack.dev.conf.js"); // 引入開發環境配置文件 /** * 根據不一樣的環境,生成不一樣的配置 * @param {String} env "development" or "production" */ const generateConfig = env => { // 將須要的Loader和Plugin單獨聲明 let scriptLoader = [ { loader: "babel-loader" } ]; let cssLoader = [ { loader: "css-loader", options: { minimize: true, sourceMap: env === "development" ? true : false // 開發環境:開啓source-map } } ]; let styleLoader = env === "production" ? ExtractTextPlugin.extract({ // 生產環境:分離、提煉樣式文件 fallback: { loader: "style-loader" }, use: cssLoader }) : // 開發環境:頁內樣式嵌入 cssLoader; return { entry: { app: "./src/app.js" }, output: { publicPath: env === "development" ? "/" : __dirname + "/../dist/", path: path.resolve(__dirname, "..", "dist"), filename: "[name]-[hash:5].bundle.js", chunkFilename: "[name]-[hash:5].chunk.js" }, module: { rules: [ { test: /\.js$/, exclude: /(node_modules)/, use: scriptLoader }, { test: /\.css$/, use: styleLoader } ] }, plugins: [ // 開發環境和生產環境兩者均須要的插件 new HtmlWebpackPlugin({ filename: "index.html", template: path.resolve(__dirname, "..", "index.html"), chunks: ["app"], minify: { collapseWhitespace: true } }), new webpack.ProvidePlugin({ $: "jquery" }) ] }; }; module.exports = env => { let config = env === "production" ? productionConfig : developmentConfig; return merge(generateConfig(env), config); };
// /build/webpack.dev.conf.js const webpack = require("webpack"); const path = require("path"); module.exports = { mode: "development", devtool: "source-map", devServer: { contentBase: path.join(__dirname, "../dist/"), port: 8000, hot: true, overlay: true, proxy: { "/comments": { target: "https://m.weibo.cn", changeOrigin: true, logLevel: "debug", headers: { Cookie: "" } } }, historyApiFallback: true }, plugins: [ new webpack.HotModuleReplacementPlugin(), new webpack.NamedModulesPlugin() ] };
// /build/webpack.comm.conf.js const ExtractTextPlugin = require("extract-text-webpack-plugin"); const CleanWebpackPlugin = require("clean-webpack-plugin"); const path = require("path"); module.exports = { mode: "production", plugins: [ new ExtractTextPlugin({ filename: "[name].min.css", allChunks: false // 只包括初始化css, 不包括異步加載的CSS }), new CleanWebpackPlugin(["dist"], { root: path.resolve(__dirname, "../"), verbose: true }) ] };
在項目目錄截圖中展現的樣式文件,vendor 下的文件還有 app.js,代碼就不一一列出了。徹底能夠根據本身的須要,寫一些簡單的代碼,而後運行一下。畢竟前面的配置文件的架構和講解纔是最重要的。
這裏僅僅給出源碼地址(歡迎 Star 哦):
/src/app.js
:https://github.com/dongyuanxin/webpack-demos/blob/master/demo16/src/app.js/src/style/
下的全部樣式文件:https://github.com/dongyuanxin/webpack-demos/tree/master/demo16/src/style/src/vendor/
下的全部腳本文件:https://github.com/dongyuanxin/webpack-demos/tree/master/demo16/src/vendor鼓搗這麼半天,確定要測試下,要不怎麼才能知道正確性(這纔是另人激動的一步啦啦啦)。
進入項目目錄,運行npm run dev
:
成功跑起來,沒出錯(廢話,都是被調試了好屢次了哈哈哈)。
打開瀏覽器的控制檯看一下:
很好,都是按照編寫的app.js
的邏輯輸出的。
按Ctrl+C
退出開發模式後,運行npm run build
,以下圖打包成功:
打包後的文件也放在了指定的位置:
直接點擊index.html
,而且打開瀏覽器控制檯:
ok, 符合app.js
的輸出:成功辨識了是不是開發環境!!!
完結撒花 ✿✿ ヽ(°▽°)ノ ✿