若是你一直跟隨我前面的博文,那麼你對webpack的基礎知識已經有比較深入的理解了。以前,咱們一直執行着:javascript
npm run build
來打包編譯輸出咱們的代碼,本文咱們來看看如何構建一個開發環境,來使咱們的開發變得方便些。css
webpack-dev-server是一個簡單的小型的web服務器,而且可以實時重載,配置也很簡單,首先安裝:html
npm install --save-dev webpack-dev-server
配置webpack.config.js:vue
devServer: { port: 8080, // 端口號 host: '0.0.0.0', // 主機名,設爲該值可經過IP訪問 overlay: { errors: true // 錯誤提示 } }
在package.json中添加命令:java
"dev": "cross-env NODE_ENV=development webpack-dev-server --config config/webpack.config.js"
執行:node
npm run dev
可見咱們的服務已經跑起來了:
webpack
在webpack打包源碼時,咱們會很難找到錯誤的出現位置,好比將源文件 sum.js、minus.js打包到bundle.js中,其中一個源文件出現了錯誤,僅僅會追蹤到bundle.js中,這對咱們來講並不理想。所以爲了更加便捷的找到錯誤的原始位置,JavaScript爲咱們提供了 source-map的功能,將編譯後的代碼映射回原始源代碼。若是一個錯誤來自於 sum.js,source map 就會明確的告訴你。 web
咱們來測試一下,在sum.js中輸出一個錯誤:npm
// ES Mudule 規範 export default function (a, b) { console.error('this is test') // 輸出錯誤 return a + b }
在沒有devtool配置的狀況下 npm run dev,會發現錯誤提示的行數並不許確,
緣由是咱們的代碼是被編譯過的
json
而後在webpack.config.js中加入配置:
devtool: 'inline-source-map', // 加入devtool配置
當配置文件改動時須要從新執行 npm run dev:
錯誤提示行數以及源碼映射都是正確的。devtool的取值有不少,你們可根據須要自行配置
模塊熱替換(Hot Module Replacement)是 webpack 提供的最有用的功能之一。它容許在運行時更新各類模塊,而無需進行徹底刷新。
使用很是簡單,在webpack.config.js中引入webpack:
const webpack = require('webpack')
在plugins數組中添加:
new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin()
給devServer中的hot屬性設爲true:
devServer: { port: 8080, // 端口號 host: '0.0.0.0', // 主機名,設爲該值可經過IP訪問 overlay: { errors: true // 錯誤提示 }, hot: true }
這樣咱們修改代碼的時候就能夠局部刷新模塊而不是刷新整個頁面了。
開發環境(development)和生產環境(production)的構建目標差別很大。在開發環境中,咱們須要具備強大的、具備實時從新加載(live reloading)或熱模塊替換(hot module replacement)能力的 source map 和 localhost server。而在生產環境中,咱們的目標則轉向於關注更小的 bundle,更輕量的 source map,以及更優化的資源,以改善加載時間。因爲要遵循邏輯分離,咱們一般建議爲每一個環境編寫彼此獨立的 webpack 配置。雖然,以上咱們將生產環境和開發環境作了略微區分,可是,請注意,咱們仍是會遵循不重複原則(Don't repeat yourself - DRY),保留一個「通用」配置。爲了將這些配置合併在一塊兒,咱們將使用一個名爲 webpack-merge 的工具。經過「通用」配置,咱們沒必要在環境特定的配置中重複代碼。
咱們先從安裝 webpack-merge 開始,用來合併webpack配置項:
npm install --save-dev webpack-merge
在config文件夾下建立 webpack.dev.js 和 webpack.build.js 並修改 webpack.config.js,將開發與生產環境的公共配置放在webpack.config.js中:
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') const MiniCssExtractPlugin = require('mini-css-extract-plugin') const isDev = process.env.NODE_ENV === 'development' const config = { entry: { main: path.join(__dirname, '../src/main.js') }, output: { filename: '[name].bundle.js', path: path.join(__dirname, '../dist') }, module: { rules: [ { test: /\.(vue|js|jsx)$/, loader: 'eslint-loader', exclude: /node_modules/, enforce: 'pre' }, { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }, { test: /\.vue$/, loader: 'vue-loader', options: createVueLoaderOptions(isDev) }, { test: /\.ejs$/, use: ['ejs-loader'] }, { test: /\.css$/, use: [ isDev ? 'vue-style-loader' : MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { importLoaders: 1 } }, 'postcss-loader' ] }, { test: /\.less$/, use: [ isDev ? 'vue-style-loader' : MiniCssExtractPlugin.loader, 'css-loader', { loader: 'postcss-loader', options: { sourceMap: true } }, 'less-loader' ] }, { test: /\.(jpg|jpeg|png|gif|svg)$/, use: [ { loader: 'url-loader', options: { name: '[path][name]-[hash:5].[ext]', limit: 1024 } } ] } ] }, plugins: [ new HtmlWebpackPlugin({ template: path.join(__dirname, '../index.html'), inject: true, minify: { removeComments: true } }) ] } module.exports = config
webpack.dev.js
const merge = require('webpack-merge') const common = require('./webpack.config.js') module.exports = merge(common, { mode: 'development', devtool: 'inline-source-map', devServer: { port: 8080, host: '0.0.0.0', overlay: { errors: true }, historyApiFallback: { index: '/index.html' } } })
webpack.build.js
const path = require('path') const CleanWebpackPlugin = require('clean-webpack-plugin') const MiniCssExtractPlugin = require('mini-css-extract-plugin') const merge = require('webpack-merge') const common = require('./webpack.config.js') module.exports = merge(common, { mode: 'production', optimization: { splitChunks: { chunks: 'initial', automaticNameDelimiter: '.', cacheGroups: { commons: { name: 'commons', chunks: 'initial', minChunks: 2, priority: 3 }, vendors: { test: /[\\/]node_modules[\\/]/, priority: 1 } } }, runtimeChunk: { name: entrypoint => `manifest.${entrypoint.name}` } }, plugins: [ new MiniCssExtractPlugin({ filename: '[name].css' }), new CleanWebpackPlugin( ['dist'], { root: path.join(__dirname, '../') } ) ] })
修改package.json的命令:
"dev": "cross-env NODE_ENV=development webpack-dev-server --config config/webpack.dev.js", "build": "cross-env NODE_ENV=production webpack --config config/webpack.build.js --progress --inline --colors"
如今分別執行 npm run dev 和 npm run build 就會獲得你想要的了。