webpac-dev-server
会帮助我们对src下面的源代码进行打包,但是打包生成的文件没有被放到dist(默认打包后的文件都放在这个文件夹中)目录下,而是放到了我们电脑中的内存里,这样可以有效地提升打包的速度,这就是webpack-dev-server隐藏的一个特性。
调试样式
我们来看一个场景:我在src目录下有一个入口文件:index.js
,有一个样式文件:style.css
,内容分别是:
//index.js
import './style.css';
var btn = document.createElement('button');
btn.innerHTML = '新增';
document.body.appendChild(btn);
btn.onclick = function () {
var div = document.createElement('div');
div.innerHTML = 'item';
document.body.appendChild(div);
}
//style.css
div:nth-of-type(odd) {
background: yellow;
}
在index.js文件中创建了一个button,每次点击button的时候,就会在页面上添加一个div,div的内容是item,在css文件中,获取到了索引为奇数的div,并让它的背景颜色为yellow,打包完成后,我在页面中添加了几个item,但是我觉得样式太单调了,于是我修改了style.css文件:
div:nth-of-type(odd) {
background: yellow;
}
div:nth-of-type(even) {
background: pink;
}
修改完成后回到页面(因为在之前我们配置了webpack-dev-server,所以现在不用我们手动去打包和刷新页面了,除非你改变了webpack的配置文件),你会发现我之前添加的内容都不见了,这样显然是不合理的,我想要的效果是我修改了css文件,页面上的样式改变而不是刷新整个页面,这个时候我们就需要用到webpack的热模块更新了。修改配置文件:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
entry: {
main: './src/index.js'
},
devServer: {
contentBase: './dist',
open: true,
port: 8080,
//下面是新增加的两行代码
hot: true, //这个属性是让webpack开启hot-module-replacement的功能
hotOnly: true //这个属性表示即便是hmr的功能没有生效,也不让浏览器自动刷新
},
module: {
rules: [{
test: /\.(jpg|png|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
limit: 10240
}
}
}, {
test: /\.(eot|ttf|svg)$/,
use: {
loader: 'file-loader'
}
}, {
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
}, {
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin(['dist']),
// 新增加的代码
new webpack.HotModuleReplacementPlugin() //使用webpack HotModuleReplacementPlugin插件
],
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
}
}
package.json配置文件:
{
"name": "lesson",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server"
},
"author": "",
"license": "ISC",
"devDependencies": {
"autoprefixer": "^9.3.1",
"clean-webpack-plugin": "^1.0.0",
"css-loader": "^1.0.1",
"express": "^4.16.4",
"file-loader": "^2.0.0",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.10.0",
"postcss-loader": "^3.0.0",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"url-loader": "^1.1.2",
"webpack-cli": "^3.1.2",
"webpack-dev-middleware": "^3.4.0",
"webpack-dev-server": "^3.1.10"
},
"dependencies": {
"webpack": "^4.25.1"
}
}
修改完成之后我们需要运行npm run start
来重新打包一下代码,然后回到页面,添加几个item,再回去修改css文件,保存文件再回到页面,你会发现我们修改的样式生效了,而且刚才添加的item也都完好无损的存在于页面中。
调试js文件
在src目录下又编写了两个js文件:
//number.js
function number() {
var div = document.createElement('div');
div.setAttribute('id', 'number');
div.innerHTML = 2000;
document.body.appendChild(div);
}
export default number;
//counter.js
function counter() {
var div = document.createElement('div');
div.setAttribute('id', 'counter');
div.innerHTML = 1;
div.onclick = function () {
div.innerHTML = parseInt(div.innerHTML, 10) + 1;
}
document.body.appendChild(div)
}
export default counter
//index.js
import counter from './counter';
import number from './number';
counter();
number();
number.js
只负责在页面中展示一个数字,counter.js
创建了一个div,div的初始内容为1,当点击div的时候,这个数字就会加一,在index.js
文件中引入了两个文件,并执行了一下函数,回到页面,我们点击div,将数字加到10,然后回去修改number.js
文件,将2000改成了3000:
div.innerHTML = 3000;
如果我们没有配置热模块更新
的话,页面就会被刷新,导致我们刚才点击到10的div又回到初始状态1,但是因为我们有配置webpack热模块更新
,所以这个div还是显示10,你会发现,虽然这个div显示是正常的,但是我们修改的number也没有变,实际上我们希望当我们修改了number文件以后,number函数可以重新执行一次,我们就需要在index.js文件中增加一段代码:
if (module.hot) { //如果当前的项目开启了hot-module-replacement,就执行下面代码
module.hot.accept('./number', () => { //如果number这个文件发生了变化,就执行下面的代码
document.body.removeChild(document.getElementById('number'));//先把之前的div从页面中删掉
number();
})
}
这段代码的意思是假设我们开启了hot-module-replacement,如果number我呢见发生了变化,就重新执行一下这个文件,这样写了以后,我们修改了number.js文件,保存文件后回到页面,就可以看到number.js对应的div的内容改变了,counter的值也没有被刷新,这样就符合我们的预期了。
但是你会发现我们之前引入css文件的时候,就不需要这个额外的处理,其实引入css文件的时候理论上也应该写这段代码,但是css-loader已经帮我们把这段代码编写了,所以就不用我们来写(拓展:vue-loader底部也实现了这段代码,我们也不用去写这段代码,react也是)。
网友评论