webpack開(kāi)發(fā)環(huán)境和生產(chǎn)環(huán)境的深入理解
以前自己寫(xiě)一小項(xiàng)目時(shí),webpack的配置基本就是一套配置,沒(méi)有考慮生產(chǎn)環(huán)境和開(kāi)發(fā)環(huán)境的區(qū)分,最近在做一個(gè)復(fù)雜的商城項(xiàng)目接觸到了webpack的高級(jí)配置,經(jīng)過(guò)兩天的研究,寫(xiě)出了一份目前來(lái)說(shuō)比叫滿意的配置,在這里分享一下。
如何區(qū)分開(kāi)發(fā)環(huán)境和生產(chǎn)環(huán)境?
眾所周知,webpack時(shí)基于node.js平臺(tái)運(yùn)行的,要區(qū)分開(kāi)發(fā)環(huán)境和生產(chǎn)環(huán)境還要存,node入手。我們啟動(dòng)webpack時(shí),都需要輸入一些命令,npm run 、yarn start之類(lèi)的,所以我們就從命令行入手,告訴webpack,當(dāng)前是什么環(huán)境。
package.json
{ "name": "webpac-demo", "version": "1.0.0", "description": "webpack練習(xí)", "main": "index.js", "scripts": { //配置開(kāi)發(fā)環(huán)境參數(shù)。注意:真實(shí)開(kāi)發(fā)中 package.json 文件中不能有注釋 "dev": "webpack --env=development", //配置生產(chǎn)環(huán)境參數(shù) "dist": "webpack --env=production", "start": "webpack-dev-server --env=development" }, "dependencies": { "font-awesome": "^4.7.0", "react": "^16.2.0", "react-dom": "^16.2.0" }, "devDependencies":{ ... } }
這樣配置,當(dāng)我們?cè)诿钚休斎?npm run dev 和 npm run dist 時(shí),就會(huì)附帶一些參數(shù)到命令行中,有了參數(shù),我們?cè)撊绾文玫侥??那就要用?node 的一個(gè)命令行參數(shù)解析引擎了。
minimist
minimist輕量級(jí)的命令行參數(shù)解析引擎
// test.js var args = require('minimist')(process.argv.slice(2)); console.log(args.hello); $ node test.js --env=production // production $ node test.js --env=development // development $ node test.js --env // true 注意:不是空字符串而是true
minimist會(huì)把參數(shù)解析成一個(gè)JSON對(duì)象:{key:value},有了這個(gè)JSON對(duì)象,我們就可以知道,當(dāng)前的命令是要執(zhí)行開(kāi)發(fā)打包,還是生產(chǎn)打包了。
// webpack.config.js const webpack = require('webpack'); //當(dāng)前項(xiàng)目的絕對(duì)路勁 const path = require('path'); // 命令行參數(shù)解析引擎 const argv = require('minimist')(process.argv.slice(2)); let env = null; switch (argv.env) { case 'production': //生產(chǎn)環(huán)境配置文件名 env = 'webpack.config.prod'; break; default: //開(kāi)發(fā)環(huán)境配置文件名 env = 'webpack.config.dev'; } console.log(`當(dāng)前是 ${argv.env} 打包`); // 這時(shí)候,我們就可以加載相應(yīng)的wabpack配置了。 module.exports = require( path.resolve( '加載的配置文件路勁',env ) );
webpack開(kāi)發(fā)環(huán)境配置和生產(chǎn)環(huán)境配置
開(kāi)發(fā)環(huán)境配置
在開(kāi)發(fā)環(huán)境下,我們首先考慮的是方便開(kāi)發(fā),方便代碼調(diào)試,不需要考慮代碼合并和css樣式分離這些。
這里主要說(shuō)三個(gè) :1.css模塊化;2.模塊熱替換功能;3.source-map(代碼映射)
// 開(kāi)發(fā)環(huán)境打包配置 const path = require('path'); const webpack = require('webpack'); const base = require('./webpack.config.base') const dfPath = require('./path') // webpack配置合并工具 const merge =require('webpack-merge') const RS = (...arg)=>path.resolve( __dirname , ...arg ) // 合并方式配置 let strategyMerge = merge.strategy({ entry: 'prepend' }); let config = { entry: { app: path.resolve(dfPath.root,'src/app.js') }, output: { path: dfPath.dist, filename: '[name].bundle.js', publicPath: '/', chunkFilename: '[name].sepChunk.js' }, module:{ rules: [ { test: /\.js$/, use:['babel-loader'], exclude: [ dfPath.node_modules ] }, { test:/\.css$/, use:[ 'style-loader', { loader:'css-loader', options:{ // css模塊化,方便多人開(kāi)發(fā) module:true, // 定義模塊化css后的類(lèi)名(默認(rèn)為hash值,可讀性差)path:路勁; name:文件名; local:本地定義的className localIdentName: '[path][name]__[local]--[hash:base64:5]' }, } ], // 排除的文件,遇到這些文件不會(huì)用當(dāng)前 loader 處理,也就不會(huì)模塊化 exclude:[ RS('./src/common'), RS('node_modules') ] }, { test:/\.css$/, use:['style-loader','css-loader'], include:[ RS('./src/common'), RS('node_modules') ] }, { test: /\.(png|jpg|jpeg|gif)$/, use: ['url-loader?limit=8192'], } ] }, plugins:[ // 模塊熱替換功能 new webpack.HotModuleReplacementPlugin() ], // 代碼映射,方便報(bào)錯(cuò)時(shí),找到對(duì)應(yīng)的源代碼 devtool: 'cheap-module-eval-source-map', devServer:{ // 服務(wù)器打包后,輸出的資源路勁 publicPath:'/', open:true } }; // 導(dǎo)出合并后的webpack配置 module.exports = strategyMerge( base , config );
生產(chǎn)環(huán)境配置
相比開(kāi)發(fā)環(huán)境,生產(chǎn)環(huán)境打包是要最后發(fā)布到服務(wù)器部署的代碼,我們需要盡量保持代碼簡(jiǎn)潔,加載性能最優(yōu),不需要調(diào)試輔助工具。
我們從這幾個(gè)方面優(yōu)化 :1.公共模塊拆分,單獨(dú)打包;2. css文件分離,單獨(dú)打包輸出;3.代碼壓縮;
// 生產(chǎn)環(huán)境配置 const webpack = require('webpack'); const base = require('./webpack.config.base') const path = require('path'); const dfPath = require('./path'); const merge = require('webpack-merge'); // 壓縮工具 const ClosureCompilerPlugin = require('webpack-closure-compiler'); // css單獨(dú)打包插件 const extractTextWebpackPlugin = require('extract-text-webpack-plugin'); const extractCSS = new extractTextWebpackPlugin('assets/css/[name]_[contenthash:6].css'); // weback合并配置 let strategyMerge = merge.strategy({ entry: 'replace', output: 'replace', module:{ rules: 'replace' } }); let config ={ entry: { // 公共模塊拆分,這些代碼會(huì)單獨(dú)打包,一般我們會(huì)把引用的框架文件拆分出來(lái),方便瀏覽器緩存,節(jié)省資源。 vender:['react'], app: path.resolve(dfPath.root,'src/app.js') }, output: { path: dfPath.dist, filename: 'assets/js/[name]_[chunkhash].bundle.js', publicPath: '/', chunkFilename: 'assets/js/[name].sepChunk.js', hashDigestLength: 6 }, module:{ rules: [ { test: /\.js$/, use:['babel-loader'], exclude: [ dfPath.node_modules ] }, /* 開(kāi)啟 css單獨(dú)打包 和 css模塊化的配置 */ { test: /\.css$/, use: extractCSS.extract({ use: [ { loader: 'css-loader', options:{ modules: true } } ] }) }, { test: /\.(png|jpg|jpeg|gif)$/, use: [ { loader: 'url-loader', options:{ limit:8192, name: '[name]_[hash].[ext]', outputPath: 'assets/img/' } } ], }, { test: /\.(mp4|ogg|svg|ico)$/, use: [ { loader: 'file-loader', options:{ name: '[name]_[hash].[ext]', outputPath: 'assets/media/' } } ] }, { test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, use: [ { loader: 'url-loader', options:{ limit:10000, name: '[name]_[hash].[ext]', outputPath: 'assets/font/', mimetype: 'application/font-woff' } } ] }, { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, use: [ { loader: 'url-loader', options:{ limit:10000, name: '[name]_[hash].[ext]', outputPath: 'assets/font/', mimetype: 'application/octet-stream' } } ] }, { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, use: [ { loader: 'file-loader', options:{ name: '[name]_[hash].[ext]', outputPath: 'assets/font/', } } ] }, { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, use: [ { loader: 'url-loader', options:{ limit:10000, name: '[name]_[hash].[ext]', outputPath: 'assets/font/', mimetype: 'image/svg+xml' } } ] }, ] }, plugins:[ extractCSS, // 設(shè)置 process.env(生產(chǎn)環(huán)境) 環(huán)境變量的快捷方式。 new webpack.EnvironmentPlugin({ NODE_ENV: 'production' }) ,new ClosureCompilerPlugin() ], devtool: 'source-map' }; module.exports = strategyMerge(base,config);
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript實(shí)現(xiàn)生成GUID(全局統(tǒng)一標(biāo)識(shí)符)
這篇文章主要介紹了JavaScript實(shí)現(xiàn)生成GUID(全局統(tǒng)一標(biāo)識(shí)符),本文寫(xiě)成了一個(gè)GUID生成類(lèi),使用也非常方便,需要的朋友可以參考下2014-09-09基于Bootstrap使用jQuery實(shí)現(xiàn)簡(jiǎn)單可編輯表格
這篇文章主要介紹了基于Bootstrap使用jQuery實(shí)現(xiàn)簡(jiǎn)單可編輯表格的相關(guān)資料,需要的朋友可以參考下2016-05-05Typescript中使用引用路徑別名報(bào)錯(cuò)的解決方法
本文主要介紹了Typescript中使用引用路徑別名報(bào)錯(cuò)的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07JavaScript實(shí)現(xiàn)修改偽類(lèi)樣式
這篇文章主要介紹了JavaScript實(shí)現(xiàn)修改偽類(lèi)樣式的方法以及代碼實(shí)現(xiàn)過(guò)程,一起學(xué)習(xí)參考下吧。2017-11-11全面了解構(gòu)造函數(shù)繼承關(guān)鍵apply call
下面小編就為大家?guī)?lái)一篇全面了解構(gòu)造函數(shù)繼承關(guān)鍵apply call。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-07-07JavaScript學(xué)習(xí)筆記之圖片庫(kù)案例分析
這篇文章主要介紹了JavaScript學(xué)習(xí)筆記之圖片庫(kù)案例,結(jié)合具體實(shí)例形式分析了javascript圖片庫(kù)相關(guān)的頁(yè)面元素動(dòng)態(tài)操作實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-01-01