NodeJS实战 - 前端构建系统
前端构建系统
- 用 npm 脚本简化复杂的命令
- 用 Gulp 管理重复性任务
- 用 Webpack 打包客户端 Web 程序
用 npm 运行脚本
- 创建定制的 npm 脚本
-
npm run script-name 可以运行任何(定制)脚本。
-
以 babel、uglify-es 为例:
{ //... "scripts": { "babel": "./node_modules/.bin/babel index.js -d build/", "uglify": "./node_modules/.bin/uglifyjs build/index.js -o build/index.min.js", "build": "npm run babel && npm run uglify" }
-
运行 npm run build 会执行那两个脚本。这是因为 Babel 和 UglifyJS 都可以作为命令行脚本执行,并且都接受命令行参数,用这个简单的命令可以组合多个前端打包工具。
三种配置前端构建工具的方法:命令行参数、单独的配置文件、配置参数添加到 package.json 中
问题也随之显现......随着构建工具的增多,我们不可能像上述这样一个个地给每个工具写配置、配参数,所以我们寻求一个自动化构建的解决方案。
用 Gulp 实现自动化构建
- Gulp 是基于流的构建系统。
- 通过对这些流的引导来创建构建过程,除了转译和缩码,还能做很多事情。
- Gulp 之所以能实现高度重用,主要归功于两项技术:使用插件和自定义构建任务。
- Gulp 任务的创建及运行如下:
// 打开gulpfile.js设置一个构建任务,用gulp.src查找JSX文件,用Babel处理ES2015和React,然后把这些文件拼到一起。
// 使用:在终端里输入gulp就可以运行这个Gulp任务。
// gulpfile.js 代码如下:
const gulp = require('gulp');
const sourcemaps = require('gulp-sourcemaps'); ←---- 像加载标准Node模块那样加载Gulp 插件
const babel = require('gulp-babel');
const concat = require('gulp-concat');
gulp.task('default', () => {
return gulp.src('app/*.jsx') ←---- 用Gulp自带的文件聚集工具gulp.src查找所有的React jsx文件
.pipe(sourcemaps.init()) ←---- 开始监视源文件,为调试构建源码映射
.pipe(babel({ presets: ['es2015', 'react']})
.pipe(concat('all.js')) ←---- 把所有源码文件拼到一个all.js中
.pipe(sourcemaps.write('.')) ←---- 单独写入源码映射文件
.pipe(gulp.dest('dist')); ←---- 将所有文件放到dist/目录下
});
根据以上代码示例总结出,在 Gulp 中,一般构建流程为:
- Gulp 监测变化 —— 构建/刷新循环
// gulp-watch插件 监测文件系统的变化
// npm i --save-dev gulp-watch
const watch = require('gulp-watch')
gulp.task('watch', () => {
watch('app/**.jsx', () => gulp.start('default'))
})
// 监测React JSX文件的变化。只要有文件发生了变化,默认的构建任务 gulp.start('default') 就会运行。
-
项目规模变大后,Gulp 任务的组织方式:
-
gulp/
-
tasks/
- task1.js
- task2.js
-
gulp/
- index.js ← 加载所有的 Gulp 任务文件
-
-
gulpfile.js ← 引入这个 gulp/index.js 文件
-
用 Webpack 构建 Web 程序 - 新一代构建工具(较 Gulp)
- 二者区别:用 Gulp 时,写 JavaScript 代码是为了驱动构建系统,所以会涉及写 gulpfile 和构建任务。而用 Webpack 时,写的是配置文件,用插件和加载器添加新功能。
- webpack 插件与加载器
- 插件:用来改变构建过程的行为,比如静态资源自动上传、文件去重等。
- 加载器:是函数,负责将输入的源文本转换为特定的文本输出, 比如转换 React 代码、CoffeeScript、SASS 或其他转译语言。
- 一个 webpack.config.js 文件
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './app/index.jsx', ←---- 输入文件
output: { path: __dirname, filename: 'dist/bundle.js' }, ←---- 输出文件
module: {
loaders: [
{
test: /.jsx?$/, ←---- 匹配所有的JSX文件
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react'] ←---- 使用Babel ES2015和React 插件
// ....
}
}
] // loaders config
} // module config
};
-
- webpack_require
- module.exports
- Webpack 把 CommonJS 模块给了我们,无须任何额外的配置,就可以使用来自 npm 的模块。