在一些简单的项目中我们仍有能力把所有JS依赖联系起来,但越来越复杂复杂的JS依赖很可能会成为困扰着我们。而且单页面应用( single-page applications, SPA, 单页面应用简介)依赖 many hefty libraries 。所以前辈们发明出了很多的构建工具,这些工具能够让我们方便的按需加载依赖,Webpack 就提供了很多这样的策略。而现在很流行的Node和他的包管理器npm让我们能更舒服的管理依赖。还有很多工具可以自动化地进行代码的语法检查、压缩等等。
Task Runners
历史上有很多的构建工具,其中 Make 或许是最出名的,到现在还是一种切实可行的选择。而 Grunt 和 Gulp 作为专业的 Task Runner 是在特别考虑到JS开发人员的情况下创建的。
通过NPM提供的插件使 Task Runner 既强大又可扩展。甚至可以使用npm script作为Task Runner,这在Webpack中尤其常见。
从名字上可以看出 Task Runner 就是运行一个一个的任务,这些任务可以是检查语法、编译、压缩等等。
Make
Make首次发布于1977年,主要用于C语言项目,但它与C语言没有任何联系。同样可以用于网页的构建工具,使用 Make 构建网站—阮一峰 这篇文章简单介绍了 Make 命令和使用方法,作者还分享了为什么构建大型项目首选 Make ,而不是 npm script、Grunt 或 Gulp。
npm scripts as a Task Runner
尽管npm CLI的主要设计目的不是用作 Task Runner,但由于package.json脚本字段的缘故,它的工作方式也是如此。请考虑下面的示例:
"scripts": {
"start": "webpack-dev-server --env development",
"build": "webpack --env production",
"build:stats": "webpack --env production --json > stats.json"
},
这些脚本可以使用npm run列出,然后使用npm run <script>执行。你还可以使用类似test:watch的约定为脚本命名。 !!#ff0000 这种方法的问题在于它要注意保持跨平台。!!
(您可能希望使用诸如 rimraf [ 以包的形式包装rm -rf命令 ] 等实用程序,而不是rm-rf。这里可以调用其他Task Runner来隐藏您实际使用的那一个。通过这种方式,您可以重构工具,同时保持接口不变。)
Grunt
这是前端开发人员的第一个有名的 Task Runner。采用了插件架构,配置复杂,难以理解。
sample:
module.exports = grunt => {
grunt.initConfig({
lint: {
files: ["Gruntfile.js", "src/**/*.js", "test/**/*.js"],
options: {
globals: {
jQuery: true,
},
},
},
watch: {
files: ["<%= lint.files %>"],
tasks: ["lint"],
},
});
grunt.loadNpmTasks("grunt-contrib-jshint");
grunt.loadNpmTasks("grunt-contrib-watch");
grunt.registerTask("default", ["lint"]);
};
grunt-webpack plugin allows you to use webpack in a Grunt environment while you leave the heavy lifting to webpack.
Gulp
Gulp采取了不同的方法。不是依赖每个插件的配置,而是处理实际的代码。
sample:
const gulp = require("gulp");
const coffee = require("gulp-coffee");
const concat = require("gulp-concat");
const uglify = require("gulp-uglify");
const sourcemaps = require("gulp-sourcemaps");
const del = require("del");
const paths = {
scripts: ["client/js/**/*.coffee", "!client/external/**/*.coffee"],
};
// Not all tasks need to use streams.
// A gulpfile is another node program
// and you can use all packages available on npm.
gulp.task("clean", () => del(["build"]));
gulp.task("scripts", ["clean"], () =>
// Minify and copy all JavaScript (except vendor scripts)
// with source maps all the way down.
gulp
.src(paths.scripts)
// Pipeline within pipeline
.pipe(sourcemaps.init())
.pipe(coffee())
.pipe(uglify())
.pipe(concat("all.min.js"))
.pipe(sourcemaps.write())
.pipe(gulp.dest("build/js"))
);
gulp.task("watch", () => gulp.watch(paths.scripts, ["scripts"]));
// The default task (called when you run `gulp` from CLI).
gulp.task("default", ["watch", "scripts"]);
配置就是处理的代码,因此遇到问题时你可以随时 hack 。可以 wrap 已有的 Node 包作为 Gulp 的插件,相较于Grunt来说你能更加清楚看到发生了什么。但是你还是需要为一些临时任务编写大量的样本文件,That is where newer approaches come in。
webpack-stream allows you to use webpack in a Gulp environment.
模块化运行时编译方案
代表是Require.js/sea.js,在 前端模块化 中已经讨论过,使用预编译会优于运行时编译。
模块化预编译方案
代表是Browserify/Webpack,和Task Runners 不同的是他们是模块化方案,而Gulp/Grunt是工具,webpack 因为loader和plugin这一配置项让他可以完成一些Gulp/Grunt的工作(虽然完成的工作有重复,但本质上他们是不同的)。Gulp/Grunt完全可以同webpack结合使用。
Browserify和Webpack相比较的话各有利弊。
总结
前端需要规范代码组织,实现模块化,所以出现了诸如webpack之类的模块化编译方案。前端需要在部署上线的时候进行检查压缩合并转换,所以出现了诸如Gulp之类的专业构建工具。而使用他们这一切都会是自动进行的。
不同的技术从不同的角度去解决问题,我们有时候可以一起使用他们。
注:在查阅资料过程中还发现了很多工具,如jspm,SystemJS、Brunch、Parcel、FIS
网友评论