标题可能不是很恰当,想不到一个合适的标题来概括我遇到以及解决的问题,暂且这样吧。

项目描述

是一个不完全与后端分离的基于 webpack 构建的 Vue 项目。

项目入口是一个 jsp 页面,其中引用了一些 jsp 模版。我想是因为有一些内容需要后端直出到页面上。
该页面上固定引用了 webpack 打包好的 css 及 js 文件路径,当然也加了动态参数用于刷新版本更新后的客户端缓存。

可以使用 webpack 命令打包,或是用 webpack --progress --colors --watch 命令启动监听模式动态构建。

这让前端开发环境变的不够友好:监听模式下修改文件后,是需要通过刷新页面获取更改的。
好像回到了传统的前端开发环境中。

解决方案

由于入口页面是由后端渲染 jsp 生成的,用 html-webpack-plugin 插件生成 html 并注入脚本、样式的法子行不通了。

热替换感觉没戏了,就想办法加个自动刷新吧。

webpack-dev-server

开始用 webpack-dev-server 代理后端服务器,可以实现监听更改、实时构建,但由于页面上的页面样式脚本引用与 webpack 构建好的文件路径匹配不上,还是获取不到更改。

var webpack = require('webpack')
var webpackDevServer = require('webpack-dev-server')
var config = require('./webpack.config')
var server = new webpackDevServer(webpack(config), {
hot: true,
quiet: false,
stats: {
chunks: false,
colors: true
},
proxy: {
'**': 'http://localhost:8080'
},
historyApiFallback: true
})
server.listen(3000)

跑了 3000 端口,页面上的文件引用依然是 8080 端口,好像是在后端就写死了。即使是我临时改了 jsp 文件的引用路径,还是需要手动刷新下页面才能获取更改。

browsersync

想起了 gulp 时代一直用的 browsersync,用它代理后端服务,监听文件变更并执行 webpack 命令,刷新浏览器。

require('shelljs/global')
var bs = require('browser-sync').create()
bs.init({
proxy: 'http://localhost:8080'
})
bs.watch('./src/**/*.*').on('change', function(){
exec('webpack', bs.reload)
})

但这样每次执行 webpack 命令,都相当于全新编译,所以速度很慢。以该项目而言,每次更改后需要等待 6s 才刷新浏览器。

还实验了 gulp + webpack-stream,属于换汤不换药,每次还是全新编译。

今天忽然想到,直接用 webpack 的监听模式启动,在每次编译后刷新浏览器就可以了。监听模式下,只有第一次是全新编译,之后会缓存未变化的模块,所以速度很快。

var webpack = require('webpack')
var webpackDevServer = require('webpack-dev-server')
var config = require('./webpack.config')
var bs = require('browser-sync').create()
var compiler = webpack(config)
bs.init({
proxy: 'http://localhost:8080'
})
compiler.watch({
aggregateTimeout: 300, // 300ms 内的文件更改聚合到一次构建中
ignored: /node_modules/, // 忽略大文件或基本不会变更的目录
poll: true
}, function(err, stats) {
bs.reload()
console.log(stats.toString({
chunks: false,
colors: true
}))
})

监听模式除了命令行启动外,也可以使用 watch 方法调用,还可以通过 ignored 配置项忽略一些不会变更的目录。
之后每次保存文件,只需要 100ms 左右就会刷新浏览器。

感叹一句

如今的前端把多少时间都耗在环境搭建上了~