自定义一个 express 服务,添加 server.js 文件,内容如下:
const express = require('express'); const webpack = require('webpack'); const webpackDevMiddleware = require('webpack-dev-middleware'); const app = express(); const config = require('./webpack.config.js'); const compiler = webpack(config); // Tell express to use the webpack-dev-middleware and use the webpack.config.js // configuration file as a base. app.use(webpackDevMiddleware(compiler, { publicPath: config.output.publicPath })); // Serve the files on port 3000. app.listen(3000, function () { console.log('Example app listening on port 3000!\n'); });添加 npm script: "server": "node server.js",
执行 npm run server, 打开 :3000/ 即是项目地址
具体事例请参考 example 目录下的 chapterFour
六、模块热替换 1. 添加 webpack 自带的插件 NamedModulesPlugin 和 HotModuleReplacementPlugin const webpack = require('webpack'); devServer: { contentBase: './dist', hot: true }, plugins: [ new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin() ], 2. 修改 index.js 文件,监听该文件所引用的外部文件的更新状况 if (module.hot) { module.hot.accept('./print.js', function() { console.log('Accepting the updated printMe module!'); printMe(); }) } 3. css 等静态资源加载了相应的 loader,会自动更新 4.其他热更新 loader 或插件React Hot Loader:实时调整 react 组件。
Vue Loader:此 loader 支持用于 vue 组件的 HMR,提供开箱即用体验。
Elm Hot Loader:支持用于 Elm 程序语言的 HMR。
Redux HMR:无需 loader 或插件!只需对 main store 文件进行简单的修改。
Angular HMR:没有必要使用 loader!只需对主要的 NgModule 文件进行简单的修改,由 HMR API 完全控制。
七、输出优化 1. 移除 JavaScript 上下文中的未引用代码(dead-code)package.json 文件设置 sideEffects 属性
"sideEffects": [ "./src/some-side-effectful-file.js", "*.css" ] 2.压缩输出,设置编译模式为 production mode: "production" 八、生产环境构建 1.构建目标比较生产环境构建目标: 更小的 bundle、更轻量的 source map、更优化的资源、更短的加载时间
开发环境构建目标: 强大的 source map 和具有热模块替换能力的 localhost server
2.针对不同环境配置 webpack(1) 安装 webpack-merge:npm install --save-dev webpack-merge
(2) 针对不同的环境创建对应的配置文件
// webpack.common.js const path = require('path'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { app: './src/index.js' }, plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title: 'Production' }) ], output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }, { test: /\.(png|svg|jpg|gif)$/, use: [ 'file-loader' ] }, { test: /\.(woff|woff2|eot|ttf|otf)$/, use: [ 'file-loader' ] }, { test: /\.(csv|tsv)$/, use: [ 'csv-loader' ] }, { test: /\.xml$/, use: [ 'xml-loader' ] } ] } }; // webpack.dev.js const merge = require('webpack-merge'); const common = require('./webpack.common.js'); const webpack = require('webpack'); module.exports = merge(common, { mode: 'development', devtool: 'inline-source-map', devServer: { contentBase: './dist' }, plugins: [ new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin() ] }); //webpack.prod.js const merge = require('webpack-merge'); const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); const common = require('./webpack.common.js'); module.exports = merge(common, { mode: 'production', plugins: [ new UglifyJSPlugin({sourceMap: true}) // 不支持 es6 语法的压缩 ] });(3) 修改 NPM Script
"start": "webpack-dev-server --open --config webpack.dev.js", "build": "webpack --config webpack.prod.js" 九、代码分离 1.针对多个文件指定对应的入口 2.把多个地方引用的代码分离到一个文件中,防止重复引用 optimization: { runtimeChunk: { name: "manifest" }, splitChunks: { cacheGroups: { commons: { test: /[\\/]node_modules[\\/]/, name: "vendor", chunks: "all" } } } } 3.动态导入 // output 添加 chunkFilename 字段 chunkFilename: '[name].bundle.js', // index.js 动态引入库,编译之后可以看到对应的 loadash-chunk async function getComponent() { var element = document.createElement('div'); element.innerHTML = _.join(['Hello', 'webpack'], ' '); return element; } getComponent().then(component => { document.body.appendChild(component); })