NPM vs. Bower vs. Browserify vs. Gulp vs. Grunt vs. Webpack
我试图总结我对最流行的JavaScript程序包管理器,打包程序和任务执行者的了解。 如果我错了,请纠正我的错误:
npm
& bower
是包管理员。 他们只是下载依赖关系,不知道如何自己构建项目。 他们知道什么是调用webpack
/ gulp
/ grunt
获取所有的依赖后。 bower
就像npm
,但是建立了扁平化的依赖树(不像npm
是递归的)。 意思是npm
为每个依赖获取依赖关系(可能会获取相同的几次),而bower
期望您手动包含子依赖关系。 有时, bower
和npm
分别用于前端和后端(因为每兆字节在前端可能都很重要)。 grunt
和gulp
是任务运行者,可自动执行所有可自动执行的任务(例如,编译CSS / Sass,优化映像,制作捆绑包并缩小/转储它)。 grunt
与gulp
(就像是maven
与gradle
或配置与代码)。 Grunt基于配置单独的独立任务,每个任务打开/处理/关闭文件。 Gulp需要的代码量较少,并且基于节点流,这使得它可以构建管道链(不重新打开相同的文件)并使其更快。 webpack
( webpack-dev-server
) - 对我来说,它是一个任务运行者,它可以让你忘记所有的JS / CSS观察者。 npm
/ bower
+插件可以取代任务跑步者。 他们的能力经常相交,所以如果你需要通过npm
+插件使用gulp
/ grunt
,会有不同的含义。 但是对于复杂任务来说,任务运行者肯定更好(例如,“在每个版本上创建捆绑包,从ES6到ES5的转储,在所有浏览器模拟器上运行它,通过ftp制作屏幕截图并将其部署到Dropbox”)。 browserify
允许为浏览器打包节点模块。 browserify
vs node
的require
实际上是AMD与CommonJS。 问题:
webpack
& webpack-dev-server
? 官方文档说这是一个模块打包程序,但对我来说,它只是一个任务运行程序。 有什么不同? browserify
? 我们不能对节点/ ES6进口做同样的事吗? npm
+插件使用gulp
/ grunt
? Webpack和Browserify
Webpack和Browserify几乎完成了同样的工作,它正在处理要在目标环境中使用的代码 (主要是浏览器,尽管您可以将其作为目标环境,如Node)。 这种处理的结果是一个或多个捆绑 - 适合于目标环境的组装脚本。
例如,假设您编写了一个分为模块的ES6代码,并希望能够在浏览器中运行它。 如果这些模块是Node模块,浏览器将不会理解它们,因为它们仅存在于Node环境中。 ES6模块在IE11等旧版浏览器中也不起作用。 此外,您可能使用了浏览器尚未实现的实验性语言功能(ES下一个提议),因此运行此类脚本只会引发错误。 像Webpack和Browserify这些工具通过将这些代码转换为表单浏览器能够执行来解决这些问题。 最重要的是,它们可以在这些捆绑上应用各种各样的优化。
然而,Webpack和Browserify在很多方面有所不同,Webpack默认提供了很多工具(例如代码分割),而Browserify只能在下载插件后才能做到这一点,但使用这两种方法会导致非常相似的结果 。 这归结于个人偏好(Webpack更时髦)。 顺便说一下,Webpack不是一个任务运行者,它只是你的文件的处理器(它通过所谓的加载器和插件来处理它们),并且它可以由任务运行者运行(以其他方式)。
Webpack开发服务器
Webpack开发服务器为Browsersync提供了类似的解决方案 - 一个开发服务器,您可以在开发服务器时快速部署应用程序,并且可以立即使用开发服务器验证开发进度,自动刷新代码更改的浏览器,甚至将更改后的代码传播到浏览器无需重新加载所谓的热模块更换。
任务运行者与NPM脚本
我一直在使用Gulp的简洁和简单的任务写作,但后来发现我根本不需要Gulp和Grunt。 我所需要的一切都可以通过使用NPM脚本来完成,通过他们的API来运行第三方工具。 在Gulp,Grunt或NPM脚本之间进行选择取决于团队的品味和经验。
虽然Gulp或Grunt中的任务很容易阅读,即使对JS不太熟悉的人也是如此,它是另一种需要和学习的工具,我个人更喜欢缩小我的依赖关系并使事情变得简单。 另一方面,用NPM脚本和运行这些第三方工具的脚本(比如,节点脚本配置和运行rimraf进行清理)替代这些任务可能更具挑战性。 但在大多数情况下, 这三者在结果上是相同的。
例子
至于示例,我建议你看看这个React初学者项目,它向你展示了覆盖整个构建和部署过程的NPM和JS脚本的完美结合。 您可以在名为scripts
的属性的根文件夹中的package.json中找到那些NPM scripts
。 在那里你将会遇到像babel-node tools/run start
这样的命令。 Babel-node是一个CLI工具(不适用于生产用途),它首先编译ES6文件tools/run
(位于工具中的run.js文件) - 基本上是一个runner工具。 这个跑步者将一个函数作为一个参数并执行它,在这种情况下是start
- 另一个实用程序(start.js)负责捆绑源文件(客户端和服务器)并启动应用程序和开发服务器(开发服务器将会是可能是Webpack Dev Server或Browsersync)。
更确切地说,start.js创建客户端和服务器端包,启动express服务器,并在浏览器同步之后成功启动,在撰写本文时,它看起来像这样(请参考反应启动器项目获取最新代码)。
const bs = Browsersync.create();
bs.init({
...(DEBUG ? {} : { notify: false, ui: false }),
proxy: {
target: host,
middleware: [wpMiddleware, ...hotMiddlewares],
},
// no need to watch '*.js' here, webpack will take care of it for us,
// including full page reloads if HMR won't work
files: ['build/content/**/*.*'],
}, resolve)
最重要的部分是proxy.target
,它们设置了他们想要代理的服务器地址,可以是http:// localhost:3000,Browsersync启动监听http:// localhost:3001的服务器,其中生成的资产被服务自动更换检测和热模块更换。 正如你所看到的,还有另一个配置属性files
包含单独的文件或模式。浏览器同步监视器用于更改并重新载入浏览器(如果有的话),但正如评论所说,Webpack负责通过HMR自己监视js源代码,所以他们在那里合作。
现在我没有任何类似的Grunt或Gulp配置的例子,但是使用Gulp(和Grunt有点相似),你可以在gulpfile.js中编写单独的任务
gulp.task('bundle', function() {
// bundling source files with some gulp plugins like gulp-webpack maybe
});
gulp.task('start', function() {
// starting server and stuff
});
在那里你会做基本上与starter-kit相同的事情,这次是与task runner一起工作的,这为你解决了一些问题,但是在学习使用过程中提出了自己的问题和一些困难,正如我所说的,你拥有更多的依赖性,更多的可能会出错。 这就是我喜欢摆脱这些工具的原因。
我也一直在寻找这个相当长的一段时间,因为这里有很多工具,每个工具都有不同的方面给我们带来好处。 这个社区分为Browserify, Webpack, jspm, Grunt and Gulp
。 你也可能听说Yeoman or Slush
。 这不是一个真正的问题,只是让每个人都想要理解一条明确的道路而感到困惑。
无论如何,我想贡献一些东西。
1.软件包管理器
软件包管理器简化了安装和更新项目依赖关系,这些依赖关系是诸如jQuery, Bootstrap
等库 - 所有在您的站点上使用且不是由您编写的内容。
浏览所有图书馆网站,下载和解压档案,将文件复制到项目中 - 所有这些都被终端中的一些命令所取代。
NPM
代表: Node JS package manager
可帮助您管理软件依赖的所有库。 您可以在名为package.json
的文件中定义您的需求,然后在命令行中运行npm install
...然后BANG,您的软件包将被下载并准备使用。 可以用于front-end and back-end
库。
Bower
:对于前端包管理,这个概念与NPM相同。 所有库都存储在名为bower.json
的文件中,然后在命令行中运行bower install
。
Bower
和NPM
最大的区别在于NPM嵌套了依赖树,而Bower需要如下的平坦依赖树。
引用Bower和npm有什么区别?
NPM
project root
[node_modules] // default directory for dependencies
-> dependency A
-> dependency B
[node_modules]
-> dependency A
-> dependency C
[node_modules]
-> dependency B
[node_modules]
-> dependency A
-> dependency D
鲍尔
project root
[bower_components] // default directory for dependencies
-> dependency A
-> dependency B // needs A
-> dependency C // needs B and D
-> dependency D
npm 3 Duplication and Deduplication
有一些更新,请打开文档以获取更多详细信息。
Yarn
:最近Facebook
发布的一个新的JavaScript
包管理器,与NPM
相比,它具有更多的优势。 使用Yarn,您仍然可以使用NPM
和Bower
注册表来获取软件包。 如果您之前安装了一个软件包, yarn
会创建一个缓存副本,以便offline package installs
。
jspm
:是SystemJS
通用模块加载器的包管理器,构建于动态ES6
模块加载器之上。 它并不是一个全新的软件包管理器,拥有自己的一套规则,而是在现有的软件包源头上运行。 开箱即用,它适用于GitHub
和npm
。 由于大部分基于Bower
的软件包都基于GitHub
,我们也可以使用jspm
来安装这些软件包。 它有一个注册表,列出了大多数常用的前端软件包,以便于安装。
查看Bower
和jspm
的不同之处:程序包管理器:Bower vs jspm
2.模块加载器/捆绑
大多数任何规模的项目都会将他们的代码分割成多个文件。 您可以将每个文件包含一个单独的<script>
标记,但<script>
建立一个新的http连接,对于小文件 - 这是模块化的目标 - 建立连接的时间可能比传输数据。 在脚本下载时,页面上不能更改内容。
例如
<head>
<title>Wagon</title>
<script src=“build/wagon-bundle.js”></script>
</head>
例如
<head>
<title>Skateboard</title>
<script src=“connectors/axle.js”></script>
<script src=“frames/board.js”></script>
<!-- skateboard-wheel and ball-bearing both depend on abstract-rolling-thing -->
<script src=“rolling-things/abstract-rolling-thing.js”></script>
<script src=“rolling-things/wheels/skateboard-wheel.js”></script>
<!-- but if skateboard-wheel also depends on ball-bearing -->
<!-- then having this script tag here could cause a problem -->
<script src=“rolling-things/ball-bearing.js”></script>
<!-- connect wheels to axle and axle to frame -->
<script src=“vehicles/skateboard/our-sk8bd-init.js”></script>
</head>
计算机可以做得比你更好,这就是为什么你应该使用一个工具来自动将所有内容捆绑到一个文件中。
然后我们听说了RequireJS
, Browserify
, Webpack
和SystemJS
RequireJS
:是一个JavaScript
文件和模块加载器。 它针对浏览器内的使用进行了优化,但可用于其他JavaScript环境,如Node
。 例如: myModule.js
// package/lib is a dependency we require
define(["package/lib"], function (lib) {
// behavior for our module
function foo() {
lib.log( "hello world!" );
}
// export (expose) foo to other modules as foobar
return {
foobar: foo
}
});
在main.js
,我们可以将myModule.js
作为依赖项导入并使用它。
require(["package/myModule"], function(myModule) {
myModule.foobar();
});
然后在我们的HTML
,我们可以参考使用RequireJS
。
<script src=“app/require.js” data-main=“main.js” ></script>
阅读关于CommonJS
和AMD
更多信息,以便轻松理解。 CommonJS,AMD和RequireJS之间的关系?
Browserify
:着手允许在浏览器中使用CommonJS
格式的模块。 因此, Browserify
不像模块Browserify
程序那样多:模块加载程序: Browserify
完全是一个构建时工具,生成一组代码,然后可以将其加载到客户端。 从安装了node&npm的构建机器开始,并获取包:
npm install -g –save-dev browserify
以CommonJS
格式编写你的模块
//entry-point.js
var foo = require('../foo.js');
console.log(foo(4));
并且,当开心时,发出命令捆绑:
browserify entry-point.js -o bundle-name.js
Browserify递归地查找入口点的所有依赖关系并将它们组装到一个文件中:
<script src=”bundle-name.js”></script>
Webpack
:它将您的所有静态资源(包括JavaScript
,图像,CSS等)捆绑到一个文件中。 它还使您能够通过不同类型的装载程序处理文件。 您可以使用CommonJS
或AMD
模块语法编写JavaScript
。 它以更基本的综合和自信的方式攻击构建问题。 在Browserify
您使用Gulp/Grunt
以及一系列转换和插件来完成工作。 Webpack
提供了足够的动力,你通常不需要Grunt
或Gulp
。 基本的用法是非常简单的。 像Browserify一样安装Webpack:
npm install -g –save-dev webpack
并通过命令一个入口点和一个输出文件:
webpack ./entry-point.js bundle-name.js
SystemJS
:是一个模块加载器, 可以在运行时导入当今使用的任何常用格式 ( CommonJS, UMD, AMD, ES6
)。 它建立在ES6
模块加载器polyfill之上,足够智能地检测正在使用的格式并正确处理它。 SystemJS
还可以使用插件来传输ES6代码(使用Babel
或Traceur
)或其他语言,如TypeScript
和CoffeeScript
。 想知道什么是node module
以及为什么它不适合在浏览器中使用。
更有用的文章:
为什么jspm
和SystemJS
?
ES6
模块化的主要目标之一是使得从互联网上的任何地方( Github
, npm
等)安装和使用任何Javascript库变得非常简单。 只需要两件事:
所以用jspm
,你可以做到。
jspm install jquery
display.js
var $ = require('jquery');
$('body').append("I've imported jQuery!");
然后,在导入模块之前,在System.config({ ... })
配置这些内容。 通常当运行jspm init
,会有一个名为config.js
的文件用于此目的。
为了使这些脚本运行,我们需要在HTML页面上加载system.js
和config.js
。 之后,我们将使用SystemJS
模块加载器加载display.js
文件。
的index.html
<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>
<script>
System.import("scripts/display.js");
</script>
注意:Angular 2已经应用了它,你也可以在Webpack
使用npm
。 由于jspm
是为了与SystemJS
集成而SystemJS
,它可以在现有的npm
源代码上npm
,所以你的答案取决于你。
3.任务跑步者
任务运行者和构建工具主要是命令行工具。 为什么我们需要使用它们:一句话就是: 自动化 。 在执行缩小,编译,单元测试,linting等重复性任务时,您需要做的工作量较少,而这些工作之前花费我们大量的时间来处理命令行,甚至手动完成。
Grunt
:您可以为您的开发环境创建自动化以预先处理代码或使用配置文件创建构建脚本,处理复杂任务似乎非常困难。 在过去几年流行。 Grunt
中的每个任务都是一组不同的插件配置,它们以严格独立的顺序方式一个接一个地执行。
grunt.initConfig({
clean: {
src: ['build/app.js', 'build/vendor.js']
},
copy: {
files: [{
src: 'build/app.js',
dest: 'build/dist/app.js'
}]
}
concat: {
'build/app.js': ['build/vendors.js', 'build/app.js']
}
// ... other task configurations ...
});
grunt.registerTask('build', ['clean', 'bower', 'browserify', 'concat', 'copy']);
Gulp
:自动化就像Grunt
一样,但不是配置,你可以用JavaScript
写流,就像它是一个节点应用程序一样。 喜欢这些天。 这是一个Gulp
示例任务声明。
//import the necessary gulp plugins
var gulp = require('gulp');
var sass = require('gulp-sass');
var minifyCss = require('gulp-minify-css');
var rename = require('gulp-rename');
//declare the task
gulp.task('sass', function(done) {
gulp.src('./scss/ionic.app.scss')
.pipe(sass())
.pipe(gulp.dest('./www/css/'))
.pipe(minifyCss({
keepSpecialComments: 0
}))
.pipe(rename({ extname: '.min.css' }))
.pipe(gulp.dest('./www/css/'))
.on('end', done);
});
查看更多:https://medium.com/@preslavrachev/gulp-vs-grunt-why-one-why-the-other-f5d3b398edc4#.fte0nahri
4.脚手架工具
Slush and Yeoman
:您可以使用它们创建初学者项目。 例如,您正在计划使用HTML和SCSS构建原型,而不是手动创建一些文件夹,如scss,css,img,fonts。 你可以安装yeoman
并运行一个简单的脚本。 然后在这里为你一切。 在这里找到更多。
npm install -g yo
npm install --global generator-h5bp
yo h5bp
查看更多:https://www.quora.com/What-are-the-differences-between-NPM-Bower-Grunt-Gulp-Webpack-Browserify-Slush-Yeoman-and-Express
我的回答与问题的内容并不完全匹配,但当我在Google上搜索这些知识时,我总是看到这个问题,因此我决定总结回答,以及为什么我们需要使用这些工具。
最近我从Grab团队那里找到了一份非常全面的指南,介绍如何在2017年实现前端开发。您可以查看下面的内容。
https://github.com/grab/front-end-guide
你可以在npmcompare上找到一些技术比较
比较browserify与grunt与gulp与webpack
正如你所看到的,webpack平均每4天发布一个新版本,维护得非常好。 但是Gulp似乎拥有他们所有人中最大的社区(Github上有超过20K星)Grunt似乎有点被忽视(与其他人相比)
所以如果需要选择一个,我会用Gulp去
链接地址: http://www.djcxy.com/p/18055.html上一篇: NPM vs. Bower vs. Browserify vs. Gulp vs. Grunt vs. Webpack
下一篇: Difference between Grunt, NPM and Bower ( package.json vs bower.json )