ES6项目主要按以下几大步骤走:
- 基础架构
- 任务自动化
- 编译工具
- 代码实现
1、基础架构主要分以下三大块:
- 业务逻辑:包括页面和交互
- 自动构建:包括编译和辅助,辅助包括自动刷新、文件合并、资源压缩
任务自动化gulp
编译工具(babel、webpack)
- 服务接口:包括数据和接口
2、开始架构(创建目录)
1)项目根目录下创建package.json文件
DOS窗口(windows环境)下进入项目根目录,运行"npm init"命令(默认已安装NodeJS和npm)
2)在项目根目录下创建三个文件夹app、server、tasks
app:业务逻辑,我们的页面实现和业务逻辑实现都放在这里,app下目录结构如下图
server:相当于在这里搭建一个测试服务器,服务接口放在该目录下,运行起来可以查看页面和功能。我们在该目录下运行“express -e .”命令来使用express脚手架搭建这一块的目录结构(默认已安装好NodeJS和express-generator(npm install express-generator -g)、express(npm install express -g)),然后运行“npm install”命令安装依赖库。搭建出来的目录结构如下图
tasks:自动化任务的构建放在这个目录下,如下图
util/args.js
import yargs from 'yargs'; //引入这个npm包来处理命令行参数
//通过使用 yargs 这个模块来处理命令行的参数,主要是方便处理命令行参数的捕获和过滤
const args = yargs
//区分线上环境还是开发环境
//通过option来提取命令行的参数,来区分命令行输入的是否有这个参数,进而来区分它是线上还是开发环境
.option('production',{
boolean:true, //表示是一个Boolean类型
default:false, /*如果在命令行中没有输入production这个项,那么参数就默认false,就是开发环境,有的话则为线上环境*/
describe:'min all scripts' //描述,不会被解析,给开发者看的,机器不识别describ
})
//设置watch参数,来控制监听开发环境中修改的这些文件要不要自动编译,也通过命令行来控制
.option('watch',{
boolean:true,
default:false,
describe:'watch all files'
})
//要不要详细地输出命令行执行的日志
.option('verbose',{
boolean:true,
default:false,
describe:'log'
})
/*Source map就是一个信息文件,里面储存着位置信息。有了它,出错的时候,除错工具将直接显示原始代码,而不是转换后的代码。*/
.option('sourcemaps',{
describe:'force the creation of sroucemaps'
})
//设置服务器端口,来启动服务器
.option('port',{
string:true,
default:8080,
describe:'server port'
})
.argv //表示对输入的命令行的内容以字符串作为解析
export default args; //最后不要忘记输出args
default.js
import gulp from 'gulp';
gulp.task('default',['build']);
build.js
import gulp from 'gulp';
import gulpSequence from 'gulp-sequence';
gulp.task('build',gulpSequence('clean','css','pages','scripts',['browser','server']));
clean.js
import gulp from 'gulp';
import del from 'del';
import args from './util/args';
gulp.task('clean',()=>{
return del(['server/public','server/views'])
})
css.js
import gulp from 'gulp';
import gulpif from 'gulp-if';
import livereload from 'gulp-livereload';
import args from './util/args';
gulp.task('css',()=>{
return gulp.src('app/**/*.css')
.pipe(gulp.dest('server/public'))
})
pages.js
import gulp from 'gulp';
import gulpif from 'gulp-if';
import livereload from 'gulp-livereload';
import args from './util/args';
gulp.task('pages',()=>{
return gulp.src('app/**/*.ejs') //打开app这个目录下的所有.ejs文件
.pipe(gulp.dest('server')) //将这些模板文件拷贝到这个server目录下
.pipe(gulpif(args.watch,livereload())) //监听热更新 注:这里的 watch 只是监听命令参数的 watch,并不是监听文件的变化。
})
scripts.js
/*
处理js的构建脚本
所有的构建脚本一定是放在tasks目录下的
*/
import gulp from 'gulp'; //整个项目的构建都是基于gulp的基础上的
import gulpif from 'gulp-if'; //gulp语句中做if判断的
import concat from 'gulp-concat'; //gulp中处理文件拼接的
import webpack from 'webpack'; //引入webpack工具包
import gulpWebpack from 'webpack-stream'; /*gulp处理的都是些文件流,它是基于stream的,所以引入webpack-stream包并结合它来做处理*/
import named from 'vinyl-named'; //对文件重命名做标志的
import livereload from 'gulp-livereload'; //热更新包,实现文件修改以后浏览器自动刷新等
import plumber from 'gulp-plumber'; // 处理文件信息流的,防止来自 gulp 插件错误导致中断操作的插件
import rename from 'gulp-rename'; // 文件重命名
import uglify from 'gulp-uglify'; // 用来处理js,css压缩的包
import {log,colors} from 'gulp-util'; //在命令行工具输出的包
import args from './util/args'; //对命令行参数进行解析的一个包(开始自己写的那个)
//创建脚本编译的任务
//task、src等是gulp提供的一个标准的API,创建一个任务
//这里的scripts是 任务的名称
//ES6的箭头函数
gulp.task('scripts',()=>{
return gulp.src(['app/js/index.js']) //打开这个文件
.pipe(plumber({ //处理常规的错误逻辑
errorHandle:function(){
}
}))
.pipe(named()) //对文件重新命名
.pipe(gulpWebpack({ /*对文件进行编译,3个参数,第一个参数是编译相应的文件,第二个是null,第三个是对错误进行一个处理*/
module:{
loaders:[{
test:/\.js$/, //如果遇到.js文件,用babel这个loader去处理
loader:'babel'
}]
}
}),null,(err,stats)=>{
log(`Finished '${colors.cyan('scripts')}'`,stats.toString({
chunks:false
}))
})
//设置文件编译完后放在哪个地方
.pipe(gulp.dest('server/public/js')) //使用gulp.dest这个命令以后,将编译好的文件写入这个路径中
//为什么要写在server目录下,是因为在server中要拿到最新的(就是编译好的)js才能在整个服务器中跑起来
//处理编译压缩的过程(三步:复制-压缩-存储)
.pipe(rename({ //可以理解成把上面生成的文件重新复制了一份
basename:'cp',
extname:'.min.js'
}))
//压缩
.pipe(uglify({compress:{properties:false},output:{'quote_keys':true}}))
//存储到这个文件夹下
.pipe(gulp.dest('server/public/js'))
/*截止现在,在server/public/js这个路径下会有两个文件,一个是编译好了未压缩的,一个是编译好的压缩了的(文件名:cp.min.js)*/
//监听一个文件,当这个文件变化了之后自动刷新
.pipe(gulpif(args.watch,livereload()))
/*解释上面:判断args.watch这个参数,如果命令行中有watch这个选项的话,就执行这个livereload()热更新,如果没有,就不会对文件进行监听,也不会刷新*/
// 注:这里的 watch 只是监听命令参数的 watch,并不是监听文件的变化。
})
browser.js
import gulp from 'gulp';
import gulpif from 'gulp-if';
import gutil from 'gulp-util';
import args from './util/args';
gulp.task('browser',(cb)=>{
if(!args.watch) return cb(); //如果没有监听,返回回调
//监听app里js,变化时调用scripts构建脚本(scripts.js),完成后es6转成es5或3,写到server目录下的文件里
gulp.watch('app/**/*.js',['scripts']);
//同理,监听app目录下的模板文件变化
gulp.watch('app/**/*.ejs',['pages']);
//同理,监听css
gulp.watch('app/**/*.css',['css']);
});
server.js
import gulp from 'gulp';
import gulpif from 'gulp-if';
import liveserver from 'gulp-live-server'; //引入一个启动服务器的包
import args from './util/args';
gulp.task('server',(cb)=>{
if(!args.watch) return cb();
//如果处于监听状态下,就创建一个服务器
var server = liveserver.new(['--harmony','server/bin/www']);
//'--harmony'表示要在当前命令行下 去执行这个控制脚本
//'server/bin/www' 就是脚本位置,其实服务器启动的就是这个脚本
server.start(); //启动服务器
//监听server这个命令下的所有js,ejs的模板引擎(当发生改变时浏览器自动刷新,实现热更新)
gulp.watch(['server/public/**/*.js','server/views/**/*.ejs'],function(file){
server.notify.apply(server,[file]); //通知服务器,文件已发生改变,然后做相应的处理
})
//监听需要重启服务的文件,app.js是整个服务启动的入口文件,router 是服务器的脚本文件,做接口用,这两个文件的改变都需要重新启动服务器才能生效
gulp.watch(['server/routes/**/*.js','server/app.js'],function(){
server.start.bind(server)() //监听到变化后,让服务重启
});
})
3)在项目根目录下创建“.babelrc”文件和“gulpfile.babel.js”文件
.babelrc
{
"presets": [
"es2015"
]
}
gulpfile.babel.js
import requireDir from 'require-dir';
requireDir('./tasks');
最后别忘了安装涉及到的依赖包!
3、构建好以上内容后,DOS窗口下回到项目根目录,运行命令“gulp --watch”即可启动服务器,然后可在浏览器中localhost:3000查看。