express+webpack+gulp+nodemon初级自动化!

主要是为了彻底解放刷新键。。。。。咳咳。开始
之前接触React时解除了webpack,不过后来看angular和其他事就搁置了。最近碰到Vue时,体验了下vue-cli 脚手架构建的项目,只能说,哇!! 好爽。。什么热加载,保存时检查代码,单元测试以及一堆我还不知道的但是很强大的功能!无比顺畅

虽然之前在用的 Gulp(盖欧破)加上各种插件貌似也能达到差不多的效果,但是还是心痒,所以这几天笨手笨脚地学者搭了这个, 一个OA的demo。

开始,主要用到:

1
2
3
4
5
6
// web框架 前端模版
express + art-template
// 自动化构建 打包(sass)
gulp + webpack +
// 浏览器刷新 node重启 热加载
browser-sync + nodemon + webpack-hot-middleware

然后新建项目,这里用express应用生成器,具体可以看这里

1
2
3
4
5
// 可能要求权限,所以sudo,这里还要感谢淘宝
sudo cnpm install express-generator -g
//express + 项目名
express myapp
//然后一路回车,塔哒,然后就好了

生成的项目模版引擎默认用的jade,前几天突然发现了国人的一款引擎art-template,性能强劲,语法干净,express亲和力又强,这次就用上了!贴上地址.

首先项目目录请看这里,然后是webpack的配置,webpack的入门看这里,先这样简单配置webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
var path = require('path');
var autoprefixer = require('autoprefixer');
var webpack = require('webpack');
//一些文件夹的路径
var ROOT_PATH = path.resolve(__dirname);
var SRC_PATH = path.resolve(ROOT_PATH, 'src');
var MODULE_PATH = path.resolve(ROOT_PATH, './node_modules');
module.exports =
// context webpack处理entry选项时的基础路径
context: path.join(__dirname, 'public'),
entry : [
// 会寻找src目录下的index.js
'../src'
],
output : {
path : '/',
filename : 'bundle.js',
},
module : {
loaders: [
{
test : /\.scss$/,
// CSS预处理器们
loaders: ['style', 'css', 'postcss', 'sass'],
include: SRC_PATH
}
]
},
// 选择postcss生效的插件
postcss: function () {
return [autoprefixer];
},
resolve: {
alias: {
// 为了全局依赖jQuery定义的地址缩写
jquery: "../node_modules/jquery/dist/jquery.min"
}
},
plugins: [
// 全局依赖jQuery
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
};

现在基本功能就是css和js打包啦,接下来加进重点,也就是热加载功能。只要你修改了webpack打包的文件,webpack会在不刷新浏览器的情况下替换掉原来的文件,无比顺畅,这里有篇文章非常非常推荐,里面很清晰的讲了webpack在各种情况下热加载的实现。进入正题,首先亮出webpack配合express的兵刃:

1
2
3
4
5
// 热加载中间件
npm install webpack-hot-middleware --save-dev
// 这个没怎么理解,感觉是生成一个虚拟的环境用来存放打包文件
npm install webpack-dev-middleware --save-dev
`

接接下来,修改webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 修改entry,output和plugins
......
entry : [
// 自己暂时理解为热加载文件存放的虚拟地址,请指正
'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000',
'../src'
],
output : {
path : '/',
filename : 'bundle.js',
// 加入publicPath
publicPath: '/javascripts'
},
.....
plugins: [
// 添加下面三行
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]

webpack配置暂时到这,然后进express的配置,这里我的是app.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 加入下面这些,有个奇怪的表现,我吧下面这些代码放在整个文件的位置不同会导致
// 功能失效,最后我放在了文件的头部。。
var webpackDevMiddleware = require("webpack-dev-middleware");
var webpackHotMiddleware = require("webpack-hot-middleware");
var webpack = require('webpack');
var webpackConfig = require('./webpack.config.js');
var compiler = webpack(webpackConfig);
app.use(webpackDevMiddleware(compiler, {
hot: true,
filename: 'bundle.js',
// 这个publicPath就是webpack里output里的那个,自己理解为dev环境下存放打包后文件的路径
publicPath: webpackConfig.output.publicPath,
stats: {
colors: true
},
historyApiFallback: true
}));
app.use(webpackHotMiddleware(compiler, {
log: console.log,
// 这个path对应entry里的path
path: '/__webpack_hmr',
heartbeat: 10 * 1000,
}));

最后在前端里引入打包文件,这样:

1
2
3
4
<!-- 其实可以看到前面webpack的context配置为 /public -->
<!-- 然后 output 的 publicPath 设置为 /javascripts -->
<!-- 所以 最后引用的地址为 (public/) javascripts/bundle.js -->
<script src="javascripts/bundle.js"></script>

塔哒,到这基本就粗略的实现了express加webpack的打包文件!!热加载,对,只有打包的文件,对于其他文件,比如node的后端代码这里的artTemplate应用在node中默认是建立缓存的,所以直接修改模版文件必须要重启下服务然后刷新浏览器才能做到视图更新,当然也可以关掉缓存这个功能

其实说白了就是监听这些文档的变化然后重启服务并刷新浏览器!!
分成两部可能更清晰点

  • 监听并重启服务
  • 在服务重启完成后刷新浏览器

这里要注意的其实就是重启服务需要点时间,看具体依赖情况,我这里大概需要1秒,所以刷新浏览器需要有个延迟,在服务完全重启完毕后再执行

先上依靠

1
2
3
4
5
npm install gulp --save-dev
npm install gulp-nodemon --save-dev
// browser-sync很有趣的,会代理起一个服务器,本身也拥有热加载功能(原理好像也是webpack?)
// 这里主要用来监听文件变化延迟刷新浏览器。
npm install browser-sync --save-dev

配置gulpfile.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
var gulp = require('gulp');
var nodemon = require('gulp-nodemon');
var path = require('path');
var bs = require('browser-sync').create();
var ROOT = path.resolve(__dirname);
var APP = path.resolve(ROOT, 'app.js');
var ROUTERS = path.resolve(ROOT, 'routes');
var VIEW = path.resolve(ROOT, 'views');
// browser-sync配置,配置里启动nodemon任务
gulp.task('browser-sync', ['nodemon'], function() {
bs.init(null, {
// 这里因为express默认起的是3000端口,所以代理3000端口到4000,随自己改
proxy: "http://localhost:3000",
port: 4000
});
});
// browser-sync 监听文件
gulp.task('default', ['browser-sync'], function () {
gulp.watch(['./routes/**/*.js','./modules/*','./database/*', './app.js', './bin/www','./views/**/*.html'], ['bs-delay']);
});
// 延时刷新
gulp.task('bs-delay', function () {
setTimeout(function () {
bs.reload();
console.log('重启完毕!');
}, 2000);
});
gulp.task('nodemon', function (cb) {
// 设个变量来防止重复重启
var started = false;
nodemon({
script: './bin/www',
// 监听文件的后缀
ext: "js html",
env: { 'NODE_ENV': 'development' },
// 监听的路径
watch: [
ROUTERS,
APP,
VIEW
]
}).on('start', function () {
if (!started) {
cb();
started = true;
}
})
});

这里可以看到,nodemon监听的文件一旦有变动后就会重启node,与此同时,其实BS也监听着这些后端文件包括artTemplate模版文件,所以一旦有改动这里再2秒后刷新浏览器。到这里差不多就可以完全解放刷新键了!

真实的体验效果么也还行,偶尔会抽风,还在继续改进。最后

收工!梅干菜丝瓜蛋汤!