前端构建工具比较

2019-08-25  本文已影响0人  小涛涛haop

在一些简单的项目中我们仍有能力把所有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

参考链接:Comparison of Build Tools

上一篇下一篇

猜你喜欢

热点阅读