sourceMap
实际应用开发过程中大部分时间都是处于开发模式中,其中需要频繁的修改代码、调试和打包。
但是打包后的代码多个模块压缩到了一个bundle文件,如果出现警告或者异常很难定位到具体模块和位置,所以webpack提供了source map的配置 devtool
,
该配置可选且具有多个配置项 ,具体包含以下:
+++ 非常快速, ++ 快速, + 比较快, o 中等, - 比较慢, -- 慢
其中 eval
、eval-source-map
、cheap-eval-source-map
、heap-module-eval-source-map
,比较适合开发环境。
更详细的信息可以查看devtool的文档
这里在原先的配置文档上添加devtool配置 devtool: ‘cheap-eval-source-map‘,
webpack-dev-server
webpack-dev-server
可以提供一个简单的 web server,并且具有 live reloading(实时重新加载) 功能。 该工具并非webpack内置,所以需要额外安装。
yarn add webpack-dev-server --dev
安装完成后在package.json
文件的script
中添加以下启动方式,--open
意思是启动后打开浏览器
"start": "webpack-dev-server --open"
然后可以在命令行中执行 npm run start
或者 yarn start
。
可以看到webpack-dev-server 在8080(默认)端口启动了一个服务。并且有一个websocket链接。这时候模块内容变更,devServer服务器就会通过websocket通知浏览器进行刷新。
此时模块都会打包到内存中,并未输出到硬盘中。
可以在webpack的配置文件中添加devServer
选项配置devServer
devServer: { // contentBase: './dist', //设置该值,devServer会到目标目录读取文件而不会打包到内存中 port: 8080 // 指定端口号,默认8080 compress: true // 一切服务都启用 gzip 压缩 proxy: { '/api': 'http://localhost:3000' } //接口代理,比如以上配置会将/api的接口都代理到 http://localhost:3000/api }
详细配置可以查看 devServer
热更替
模块热替换(hot module replacement 或 HMR)是 webpack 提供的最有用的功能之一。它允许在运行时更新所有类型的模块,而无需完全刷新。改模式仅适用于开发模式
mode: development
要想使用模块热更替,需要借助webpack内置的HotModuleReplacementPlugin
,
const webpack = require('webpack') devServer:{} plugins: [ derServer: { hot: true, }, new webpack.HotModuleReplacementPlugin(), ]
接着在src目录下新建一个print.js
文件,导出一个print函数
src/print.js
export default function pring(){ console.log('log A') }
在index.js中引入print.js,并且在底部添加部分代码
import _ from 'lodash' import print from './print' import './style.css' import ImgFile from './asset/tim.jpg' function createComponent(tag) { let element = document.createElement(tag) element.innerHTML = _.join(['Hello', 'webpack'], ', ') element.classList.add('red') let img = new Image() img.src = ImgFile element.append(img) print() //log something return element } document.body.append(createComponent('div')) if(module.hot){ module.hot.accept('./print.js', function(){ print() console.log('模块热更新啦!') }) }
完成以上工作后重启devServer服务器。
查看浏览器控制台可以看到 print打印的信息log A
以及热更替启用的信息
这时候修改print.js,添加多一条打印信息
export default function pring(){ console.log('log A') console.log('log B') }
以上就完成了热更新的基本配置。
但是还有个问题,就是修改index.js的内容时不会触发热更新。
这是因为在这段代码中的module.hot.accept
函数第一个参数 接收的是./print.js
文件的绝对路径,如果热更替的时候只会执行print的模块代码。
一般这种情况的解决方案是把应用的入口逻辑放到另外一个app.js模块文件中,然后在index.js中引入该模块,重新执行该模块的代码。
PS: css文件的热更替使用style-loader。
对于 React 和 Vue 可以使用
React Hot Loader
Vue Loader
完整的webpack.config.js 文件
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') const MiniCssExtractPlugin = require('mini-css-extract-plugin') const { CleanWebpackPlugin } = require('clean-webpack-plugin') module.exports = { entry: { app: path.resolve(__dirname, './src/index.js') }, output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, devtool: 'cheap-eval-source-map', module: { rules: [ { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, 'css-loader' ] }, { test: /\.(jpg|jpeg|png|bmp)$/, use: [ { loader: 'file-loader', options: { name: 'img/[name].[ext]' } } ] } ] }, devServer: { hot: true, }, plugins: [ new HtmlWebpackPlugin(), new MiniCssExtractPlugin({ filename: 'css/style.css' }), new CleanWebpackPlugin() ] }