webpack工程化08(webpack dev server)
webpack搭建服务有几种方式,第一种:webpack watch mode 已命令行方式执行配置文件启动服务(基本不用);第二种:webpack-dev-server 这也是webpack官方推荐的方式(最常见);第三种:express + webpack-dev-middleware 可以更加灵活的自定义服务(更灵活,但难度也会高一点)
本文只讲第二种和第三种。
1.webpack-dev-server
webpack-dev-server的功能其实非常强大,比如我们最熟悉的模块热更新,接口代理,路劲重定向,live reloading等
我们来看一下devServer的一些配置
contentBase:静态文件的路径,port:端口,historyApiFallback:地址指向,https:支持https,proxy:代理,hot:热更新,openpage:启动服务打开的页面,lay:懒加载,overlay:错误提示是否在html上遮罩提示
我们直接来看一个最简单的demo
//webpack.config.js
const path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: path.resolve(__dirname, 'src/app.js')
},
output: {
filename: '[name]-[hash:5]-bundle.js',
path: path.resolve(__dirname,'dist')
},
devServer: {
port: '8080'
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'index.html')
})
]
}
然后在package.josn文件的script中加一条脚本。
"dev": "webpack-dev-server --open"
然后执行 npm run dev 启动服务,服务成功启动。
在index.html中写个hello word,页面自动更新,在devServer下,文件打包在内存中,所以dist文件是不会生产的。
下面来看一下常见的一些配置
inline设置为false之后,在页面头部会显示一个编译的进程,而inline为true的话,编译信息会显示在console里面。(一般为true)
当我们输入一个不存在的路由的时候,页面往往会报一个404或者提示找不到页面
如果我们把historyApiFallback设为true就不会有这个问题,而且historyApiFallback可以自定义页面的路径跳转和显示。(可用正则)
historyApiFallback: {
rewrites: [
{
from: '/test/a',
to: '/test/a.html'
}
]
}
我们在跟目录建一个test文件夹,里面放一个a.html。当我们改变地址的时候就会跳转到a.html页面
Proxy:这个配置也是很重要的,因为在项目中接口的请求往往是跨域访问的,所以需要proxy来做代理。proxy有几个参数,target代理目标,changeOrigin可以改变访问的源,headers请求头信息,pathRewrite地址重写。
举个例子。
我们先引入axios,用来请求接口,target接口地址是我博客的一个地址,因为我的博客地址也是以api开头,所以需要pathRewrite把/api替换成/api
const path = require('path')
const webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: path.resolve(__dirname, 'src/app.js')
},
output: {
filename: '[name]-[hash:5]-bundle.js',
path: path.resolve(__dirname,'dist')
},
devServer: {
inline: true,
port: '8080',
historyApiFallback: true,
proxy: {
'/api': {
target: 'https://api.yeshaojun.com',
changeOrigin: true,
pathRewrite: {
'/api': '/api'
}
}
}
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'index.html')
}),
new webpack.ProvidePlugin({
axios: 'axios'
})
]
}
//app.js
setTimeout(function() {
axios.get('/api/newslist').then(res=> {
console.log(res)
})
},2000)
我们可以看到,接口就请求成功了。
下面介绍一下模块热更新,这个几乎是项目必用的一个功能,好处也很明显,不会刷新页面,只更新我们修改的内容,让我们调试更加方便。
在配置文件中,将hot设置true,同时在插件中使用webpack.HotModuleReplacementPlugin,这样模块热更新就配置完了。
但是在实际的热更新中,一般先通过loder来处理,然后再进行热更新。
css的热更新依赖于style-loader,js的热更新一般依赖于框架提供的loader,比如vue-loader
当然也可以自己配置。
直接看demo
//app.js
import './A.css'
var div = document.getElementById('app')
div.innerHTML = 'hello word111'
div.setAttribute('class', 'test')
//A.css
.test {
background: #000;
color: #fff;
}
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: path.resolve(__dirname, 'src/app')
},
output: {
filename: '[name]-[hash:5]-bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader','css-loader']
}
]
},
devServer: {
port: '8080',
hot: true
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'index.html')
})
]
}
运行之后,修改.test背景色,发现页面没有刷新,背景直接变色了,可见css的热更新是好的。
修改div.innerHTML发现页面刷新了,很显然js并没有实现热更新。
在app.js中加两行代码
if(module.hot) {
module.hot.accept()
}
至此,js热更新也实现了。
开发cheap-module-scoure-map,生产:scoure-map