(翻译)前端构建工具的比较

原文地址:https://survivejs.com/webpack/appendices/comparison/

在以前,是可以将你的脚本写在一起。 时代已经改变,现在将JavaScript代码分开来可能是一个复杂的工作。 随着单页应用程序(SPA)的兴起,这个问题已经升级。他们倾向于依靠一些有用的系统(来解决这个问题)。

出于这个原因,有多种策略来加载它们。您可以立即加载它们,或者考虑需要它们时加载。Webpack支持许多这样的策略。

Node和npm的流行,给它的包管理器提供了更多的使用环境。在npm普及之前,很难使用依赖项。有一段时间,人们开发出了前端特定的包管理器,但npm最终赢得了胜利。现在依赖管理比以前更容易了,尽管还需要克服一些挑战。

任务运行程序与打包

历史上,已经有很多构建工具。 Make可能是最着名的,它仍然是一个可行的选择。 专门的任务运行程序,如Grunt和Gulp,是专门为JavaScript开发人员创建的。 通过npm提供的插件使得任务运行程序都强大而且可扩展。 甚至可以使用npm脚本作为任务运行程序。 这很常见,特别是webpack。

任务运行程序是高水平的伟大工具。 它们允许您以跨平台方式执行操作。 当您需要将各种资源拼接在一起并生产时,问题就会开始。 出于此原因,存在资源整合程序,如Browserify,Brunch或webpack。

有一段时间,RequireJS很受欢迎。 它的核心是提供一个异步模块的方法并建立在此之上。 AMD的格式在后面将会有更详细的介绍。 幸运的是,这些标准已经赶上了,而且RequireJS似乎是一个很好的启发。

Make

就像1977年最初发布的那样,Make回来了。尽管它是一个旧工具,但它仍然是相关的。 Make允许您为各种目的编写单独的任务。 例如,您可以有不同的任务来创建生产构建,压缩JavaScript或运行测试。 您可以在许多其他工具中找到相同的方法。

尽管Make主要用于C项目,但它并不以任何方式与C绑定。 James Coglan详细讨论了如何使用在JavaScript中使用Mark。 看一下下面的詹姆斯帖子里介绍的压缩代码的方法:

Makefile

PATH  := node_modules/.bin:$(PATH)
SHELL := /bin/bash
 
source_files := $(wildcard lib/*.coffee)
build_files  := $(source_files:%.coffee=build/%.js)
app_bundle   := build/app.js
spec_coffee  := $(wildcard spec/*.coffee)
spec_js      := $(spec_coffee:%.coffee=build/%.js)
 
libraries    := vendor/jquery.js
 
.PHONY: all clean test
 
all: $(app_bundle)
 
build/%.js: %.coffee
    coffee -co $(dir $@) $<
 
$(app_bundle): $(libraries) $(build_files)
    uglifyjs -cmo $@ $^
 
test: $(app_bundle) $(spec_js)
    phantomjs phantom.js
 
clean:
    rm -rf build

使用Make,您可以使用Make-specific语法和终端命令为您的任务建模,使其可以与webpack集成。

RequireJS

RequireJS可能是第一个成为真正受欢迎的脚本加载程序。 它首先正确地引入了模块化JavaScript。 其最大的吸引力是AMD。 它引入了一个定义包装器:

define(['./MyModule.js'], function (MyModule) {
  return function() {}; // 模块入口
});
 
// 或者
define(['./MyModule.js'], function (MyModule) {
  return {
    hello: function() {...}, // 导出为模块函数
  };
});

顺便说一下,可以在包装器中使用require:

define(['require'], function (require) {
  var MyModule = require('./MyModule.js');
 
  return function() {...};
});

后一种方法更简洁一点。 但您仍然会遇到多余的代码。 ES6等标准解决了这个问题。

注意:Jamund Ferguson撰写了一篇关于如何从RequireJS移植到webpack的优秀博客系列。

npm脚本作为自动化构建工具

即使npm CLI(命令行界面)并非主要用于作为任务运行的程序,由于有package.json的脚本字段是之成为可能。 考虑下面的例子:

package.json

"scripts": {
  "stats": "webpack --env production --json > stats.json",
  "start": "webpack-dev-server --env development",
  "deploy": "gh-pages -d build",
  "build": "webpack --env production"
},

这些脚本可以使用npm run列出,然后使用npm run <script>执行。 您还可以使用诸如test:watch这样的约定命名空间。 这种方法可以使它保持跨平台。

取代使用rm -rf,您可能更希望使用诸如rimraf等实用程序。 在这里可以调用其他自动化构建工具来隐藏你正在使用的具体细节。 这样,您可以在保持界面相同的情况下使用重构工具。

Grunt


Grunt在前端开发人员中是最受欢迎的。它的插件架构有助于它的流行,插件本身通常是复杂的,因此,当配置增加时,很难理解到底发生了什么。

以下是Grunt文档的示例。 在此配置中,您定义一个linting和一个观察任务。 当watch任务运行时,它也会触发lint任务。 这样,当您运行Grunt时,您可以在编辑源代码时在终端中实时发出警告。

Gruntfile.js

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有用的一个重要部分是它隐藏了大量的细节。

从远来说,这可能会有问题。从Grunt的构建过程,你很难理解它引擎工作的具体情况。

注意:grunt-webpack插件允许您在Grunt环境中使用webpack,同时将使用等级提升到Webpack。

Gulp


Gulp采取不同的方法。 您不需要依赖每个插件的配置,而是处理实际的代码。 Gulp建立在管道概念之上。 如果你熟悉Unix,这里也是一样的。 您需要遵循以下概念:

  • 来源匹配文件。
  • 对来源执行操作的过滤器(例如,转换为JavaScript)
  • 接收模块库(例如,您的构建目录)在哪里管理构建结果。

这是一个示例的Gulpfile,可以让您更好地了解从项目的README中获取的方法。 它被缩写为一个接口:

Gulpfile.js

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']
};
 
// 并不是所有的任务都需要使用流
// 一个gulpfile是另一个节点程序
// 你也可以在npm上使用所有的软件包
gulp.task(
  'clean',
  del.bind(null, ['build']
);
 
gulp.task(
  'scripts',
  ['clean'],
  () => (
    // 压缩和复制所有的JavaScript(除了供应商脚本)
    // 源代码一路下来
    gulp.src(paths.scripts)
      // 管道内
      .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.bind(null, paths.scripts, ['scripts'])
);
 
// 默认任务(从CLI运行`gulp`时调用)
gulp.task(
  'default',
  ['watch', 'scripts']
);

鉴于配置是代码,如果遇到麻烦,您总是可以将其删除。 您可以将现有的节点包作为Gulp插件,等等。 与Grunt相比,您可以更清楚地了解发生了什么。 尽管如此,你仍然最终写了很多模板作为闲时任务。 那就是更新的方法。

注意:webpack-stream允许您在Gulp环境中使用webpack。

注意:Fly是与Gulp类似的工具。 它依赖于ES6发生器。

Browserify


处理JavaScript模块一直是一个问题。 js语言本身没有模块的概念,直到ES6。 Ergo,这个语言在90年代被用在浏览器环境中。 已经提出了包括AMD在内的各种解决方案。

Browserify是模块问题的一个解决方案。 它可以将CommonJS模块捆绑在一起。 您可以将其与Gulp挂钩,您可以找到较小的转换工具,使您可以超越基本用法。 例如,watchify提供了一个在开发空闲的工作期间为您创建捆绑包的文件监视器。

Browserify生态系统由很多小模块组成。 这样,Browserify就符合Unix的理念。 Browserify比webpack更容易采用,实际上它是一个很好的替代品。

注意:Splittable是一个Browserify包装器,允许代码分割,支持ES6开箱即用,Tree shaking等等。

JSPM


使用JSPM与以前的工具截然不同。 它附带了一个自己的命令行工具,用于将新的软件包安装到项目中,创建一个生产包,等等。 它支持SystemJS插件,可以将各种格式加载到项目中。

Brunch


与Gulp相比,Brunch在更高层次的抽象上运作。 它使用类似于webpack的声明方法。 以示例为例,您可以考虑从Brunch网站改编以下配置:

module.exports = {
  files: {
    javascripts: {
      joinTo: {
        'vendor.js': /^(?!app)/,
        'app.js': /^app/,
      },
    },
    stylesheets: {
      joinTo: 'app.css',
    },
  },
  plugins: {
    babel: {
      presets: ['es2015', 'react'],
    },
    postcss: {
      processors: [require('autoprefixer')],
    },
  },
};

Brunch包括像brunch new, brunch watch --server, and brunch build --production。 它包含了很多创造性的功能,可以使用插件扩展。

注意:Brunch有一个实验性的热模块重新加载程序

Webpack


您可以说Webpack采用比Browserify更单一的方法。 Browserify由多个小工具组成,而Webpack提供了一个核心,它提供了很多创造性的功能。

Webpack核心可以使用特定的加载程序和插件进行扩展。 它可以控制如何解决模块,使您可以调整您的构建以匹配特定情况和解决无法正常运行的软件包。

与其他工具相比,Webpack具有初始复杂性,但通过其广泛的功能集成可以弥补这一点。 这是一个需要耐心的高级工具。 但是一旦了解了背后的基本思路,webpack就变得很强大。

其他选项

您可以找到更多替代品,如下所列:

  • pundle宣传自己作为下一代打包工具,并特别注意其性能。
  • Rollup重点关注打包es6的代码。Tree shaking是其卖点之一。您可以使用Rollup与webpack的加载程序rollup-loader
  • AssetGraph采用完全不同的方法,建立在HTML语义之上,使其成为超链接分析结构分析的理想选择。webpack-assetgraph-plugin将webpack和AssetGraph结合在一起。
  • FuseBox是一个专注于速度的打包工具。 它采用零配置方式,旨在开箱即用。
  • StealJS是一个依赖加载器,一个专注于性能和易用性的构建工具。
  • Flipbox将多个捆绑包裹在一个统一的界面后面。

结语

历史上已经有很多JavaScript的构建工具。 每个人都试图以自己的方式解决一个特定的问题。 这些标准已经开始迎头赶上,基本语义的要求也更少了。 相反,工具可以在更高层次上竞争,并推动更好的用户体验。 通常,您可以一起使用几个单独的解决方案。

总的来说:

  • 自动化构建工具和打包工具解决不同的问题。 您可以通过两者实现类似的结果,但通常最好将它们一起使用来相互补充。
  • 较早的工具(如Make或RequireJS)仍然具有影响力,即使它们在前端开发中不如以往那样受欢迎。
  • Bundinner如Browserify或webpack解决了一个重要的问题,并帮助您管理复杂的Web应用程序。
  • 一些新兴技术从不同的角度解决问题。 有时候它们建立在其他工具之上,有时它们可以一起使用。

原博客备份

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270