想要在代码发生变化后自动编译代码,有三种在方式:
文件更新,代码重新编译,不必手动运行整个构建过程,但还需要刷新浏览器 | |
webpack-dev-server | 同上,但可以自动刷新页面 |
webpack-dev-middleware | espress的中间件,用来定制化整个watch和刷新的过程,, |
1、什么是webpack-dev-server
项目最终要打包上线,所以最好能模拟线上环境进行开发调试,,即开始服务
webpack-dev-server就是一个让我们可以模拟线上环境进行项目调试的工具
2、webpack-dev-server提供的额外常用功能
1)路径重定向
把找不到的路径重新定向,防止出现找不到文件的错误
2)浏览器中显示编译错误
3)接口代理
解决跨域问题
4)热更新
不刷新浏览器的情况下,对代码进行更新
3、webpack-dev-server使用步骤
安装 webpack-dev-server --> 配置devServer字段 --> 利用命令行开启服务
webpack.config.js
devServer: { port: 9001, },
package.json "scripts": { "test": "echo "Error: no test specified" && exit 1", "dev": "webpack-dev-server" },
4、devServer常用配置
1)inline:状态 服务的开始模式 浏览器上多了个状态条
2)lazy:懒加载 多入口,如果不配置,会对所有入口进行编译,如果配置lazy,则只有当访问该入口时,才会对该入口进行编译,从而提高打包和编译的速度
3)port:配置端口
4)overlay:错误遮罩 通常,错误会显示在控制台,开启overlay之后,错误会显示在页面的一个遮罩中
5)historyApiFallback:路径重定向 做404效果
简单配置为 historyApiFallback: true ,,,则输入 错误路径,页面不会发生跳转,也不会出现报错
historyApiFallback: { rewrites: [ //可以是一个或多个 { from: /^/([ -~]+)/, to: function(context){ //context为上面正则匹配到的内容 if(context) { return './' + context.match[1] + '.html' }else { return './404.html' } } } ] }
6)proxy:代理请求 跨域把客户端请求转化为webpack-dev-server,也就是用webpack-dev-server代理我们的请求,通过webpack-dev-server转发,从而解决跨域的问题
proxy: { '/': { // '/'属性名表示碰到以'/'开头的地址,就进行代理转发 target: '', // target表示把请求转发到哪个地址去 changeOrigin: true, // changeOrigin 改变请求origin的作用 pathRewrite: { // 接口名较长进行简化 '^comments': '/api/comments' }, headers: { // 要被代理的请求上加的请求头 } }, '/api': { //想配置多个匹配规则就增加配置即可 } }
7)hot:热更新 用于在无刷新的情况下,根据文件变化动态刷新页面的局部状态
每次都全量刷新整个页面,在大型应用开发中,体验很不好,1是加载速度慢,2是很多操作状态(弹窗会随页面刷新消失),这时候可以使用webpack的HMR
HMR(模块热替换)
devServer: { hot: true, hotOnly: true, //只使用热更新,不适用浏览器刷新 }
HMR原理:
import component from './component' let demoComponent = component() document.body.appendChild(demoComponent) // HMR 接口 if(module.hot) { // 捕获热更新 module.hot.accept("./compent", () => { const nextComponent = component() // 用新的内容替换来的内容 document.body.replaceChild(nextComponent, demoComponent) demoComponent = nextComponent }) }
实际编写中,不需要自己编写具体逻辑,因为vue,react都提供了对应webpack-loader来做这些脏活累活,vue-loader,react-hot-loader
5、source-map
为方便调试,我们需要知道打包后的代码对于原文件的位置
1)如果代码有一处错误,无source-map只能追踪到错误发生在打包后文件的哪个位置,但是打包后的文件不方便阅读
2)有了source-map,就可以查看错误发生在原模块的哪个地方
devtool: 'eval-source-map',
cource-map的模式
开发模式 eval eval-source-map cheap-eval-source-map cheap-module-source-map
生产模式 source-map hidden-source-map nosource-source-map
// 终极配置 const webpack = require('webpack') const extractTextCss = require('extract-text-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports={ mode:'production', entry:{ app:'./src/app.js', }, output:{ path:__dirname+"/dist", filename:'[name].bundle.js' }, module:{ rules:[ { test:/.less$/, use:extractTextCss.extract({ fallback:{ loader:'style-loader', options:{ //insertInto:"#mydiv", singleton:true, //transform:"./transform.js" } }, use:[ { loader:'css-loader', options:{ modules:{ localIdentName:'[path][name]_[local]_[hash:4]' } } }, { loader:'less-loader' } ] }) } ] }, devtool: 'eval-source-map', devServer: { port: 9001, inline: false, hot: true, hotOnly: true, overlay: true, historyApiFallback: { rewrites: [ //可以是一个或多个 { from: /^/([ -~]+)/, to: function(context){ //context为上面正则匹配到的内容 return './' + context.match[1] + '.html' } } ] }, proxy: { '/smartSpec': { // '/'属性名表示碰到以'/'开头的地址,就进行代理转发 target: 'https://mooc.study.163.com/', // target表示把请求转发到哪个地址去 changeOrigin: true, // changeOrigin 改变请求origin的作用 pathRewrite: { // 接口名较长进行简化 "^/smartSpec/qd":"/smartSpec/detail/1202816603.htm" }, headers: { // 要被代理的请求上加的请求头 } }, } }, plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', template: './src/index.html', minify: { collapseWhitespace: true }, inject:true, }), new extractTextCss({ filename:"app.bundle.css", disable:true }), ] }