给咕unt靴! 使用npm作为构建工具的指南

前端构建和工作流工具种类繁多GruntGulpBroccoliJake等等。 这些工具几乎可以使您发现自己在项目中重复执行的几乎所有操作自动化,从缩小和连接源文件到运行测试或编译代码。 但是问题是,您是否需要它们? 您是否真的要为您的项目引入额外的依赖关系? 答案是不!”。 有一个免费的替代方案可以为您完成大多数任务,并且与Node.js捆绑在一起。 当然我在说npm

在本文中,我们将讨论npm可以用作构建工具的功能。 如果您想在开始前快速阅读npm,请参阅npm的初学者指南 。 如果您想继续学习,可以在GitHub上找到本文中使用的代码

npm脚本

为了开始讨论,我们将为新的演示项目创建目录,我们将其称为“ buildtool”。 完成后,我们将移至该文件夹,然后运行命令npm init创建package.json文件:

$ mkdir ~/buildtool && cd ~/buildtool
$ npm init

您将被问到几个问题。 随意跳过全部或部分内容,因为您将package.json文件的最终内容替换为以下内容:

{
  " name ": "buildtool" ,
  " version ": "1.0.0" ,
  " description ": "npm as a build tool" ,
  " dependencies ": {} ,
  " devDependencies ": {} ,
  " scripts ": {
    " info ": "echo 'npm as a build tool'"
   } ,
  " author ": "SitePoint" ,
  " license ": "ISC"
 }

正如你所看到的,我们有一个scripts与对象property称为infoinfo的值将作为命令在Shell中执行。 通过运行以下命令,我们可以看到scripts属性(也称为command )和在项目中定义的值的列表:

$ npm run

如果在我们的项目文件夹中运行上一个命令,则应看到以下结果:

Scripts available in buildtool via `npm run-script`:
  info
    echo 'npm as a build tool'

如果要运行特定属性,可以运行以下命令:

$ npm run <property>

因此,要运行我们在package.json文件中定义的info命令,我们必须编写:

$ npm run info

它将产生以下输出:

$ npm run info
> buildtool@ 1.0 . 0 info /home/sitepoint/buildtool
> echo 'npm as a build tool'

npm as a build tool

如果只需要info的输出,则可以使用-s标志, 使npm的输出静音

$ npm run info -s
npm as a build tool

到目前为止,我们仅使用了简单的echo ,但这是一个非常强大的功能。 命令行上的所有内容都对我们可用,我们在这里可以很有创造力。 因此,让我们以到目前为止所介绍的内容为基础,并安装一些packages以创建一些通用的工作流程。

常见工作流程

我们要实现的第一件事是对JavaScript文件的整理功能。 这涉及到运行一个程序,该程序将分析我们的代码中是否存在潜在错误。 我们将为此使用JSHint ,因此第一步是通过npm安装软件包:

$ npm install jshint --save-dev

执行此命令后,您将看到一个名为node_modules的新子文件夹。 这是JSHint的下载位置。 此外,我们还需要为项目创建以下文件夹结构:

├── assets
│   ├── css
│   │   └── main .css
│   └── scripts
│       └── main .js
├── dist
├── package .json
├── node_modules
└── test
    └── test .js

在Unix系统上,可以使用以下命令完成此操作:

$ mkdir -p assets/css assets/scripts test && touch assets/css/main.css assets/scripts/main.js test/test.js

林亭

现在,我们将在main.js文件中强加一些语法错误。 目前文件为空,因此将其打开并粘贴以下内容:

"use strict" ;

var Author = new function (name) {
  this .name = name || "Anonymous" ;
  this .articles = new Array ();
}

Author.prototype.writeArticle = function (title) {
  this .articles.push(title);
};

Author.prototype.listArticles = function () {
  return this .name + " has written: " + this .articles.join( ", " );
};

exports.Author = Author;

var peter = new Author( "Peter" );
peter.writeArticle( "A Beginners Guide to npm" );
peter.writeArticle( "Using npm as a build tool" );
peter.listArticles();

希望这段代码的意图很清楚-我们正在声明一个构造函数,其目的是创建新的Author对象。 我们还将一些方法附加到Authorprototype属性上,这将使我们能够存储和列出作者编写的文章。 注意exports语句,它将使我们的代码在定义它的模块之外可用。 如果您想了解更多有关此的信息,请务必阅读: 了解Node.js中的module.exports和exports

接下来,我们必须在package.jsonscripts对象中添加一个property ,该property将触发jshint 。 为此,我们将创建一个lint属性,如下所示:

"scripts" : {
  " info ": "echo 'npm as a build tool'" ,
  " lint ": "echo '=> linting' && jshint assets/scripts/*.js"
 }

在这里,我们利用&&运算符来链接命令和文件通配符(星号),这些通配符被视为通配符,在这种情况下,它将匹配任何以script目录结尾的.js文件。

注意 :Windows命令行不支持glob,但是当给定命令行参数(例如*.js ,Windows会将其逐字传递给调用应用程序。 这意味着供应商可以安装兼容性库以提供Windows glob类功能。 JSHint为此使用minimatch库。

现在让我们看一下代码:

npm run lint -s

这将产生以下输出:

=> linting
assets/scripts/main.js: line 1 , col 1 , Use the function form of "use strict" .
assets/scripts/main.js: line 5 , col 28 , The array literal notation [] is preferable.
assets/scripts/main.js: line 3 , col 14 , Weird construction. Is 'new' necessary?
assets/scripts/main.js: line 6 , col 1 , Missing '()' invoking a constructor.
assets/scripts/main.js: line 6 , col 2 , Missing semicolon.
assets/scripts/main.js: line 16 , col 1 , 'exports' is not defined.

6 errors

有用。 让我们清理这些错误,重新运行linter来确保,然后进行一些测试:

( function () {
  "use strict" ;

  var Author = function (name) {
    this .name = name || "Anonymous" ;
    this .articles = [];
  };

  Author.prototype.writeArticle = function (title) {
    this .articles.push(title);
  };

  Author.prototype.listArticles = function () {
    return this .name + " has written: " + this .articles.join( ", " );
  };

  exports.Author = Author;

  var peter = new Author( "Peter" );
  peter.writeArticle( "A Beginners Guide to npm" );
  peter.writeArticle( "Using npm as a build tool" );
  peter.listArticles();
})();

注意我们如何将所有内容包装在立即调用的函数表达式中

npm run lint -s
=> linting

没有错误。 我们很好!

测试中

首先,我们需要安装mocha软件包 。 Mocha是针对Node.js和浏览器的简单但灵活的JavaScript测试框架。 如果您想了解更多有关本文的内容,那么这篇文章是个不错的起点: 使用Mocha&Chai进行基本前端测试

npm install mocha --save-dev

接下来,我们将创建一些简单的测试来测试我们先前编写的方法。 打开test.js并添加以下内容(请注意require语句,该语句使我们的代码可用于mocha):

var assert = require ( "assert" );
var Author = require ( "../assets/scripts/main.js" ).Author;

describe( "Author" , function () {
  describe( "constructor" , function () {
    it( "should have a default name" , function () {
      var author = new Author();
      assert.equal( "Anonymous" , author.name);
    });
  });

  describe( "#writeArticle" , function () {
    it( "should store articles" , function () {
      var author = new Author();
      assert.equal( 0 , author.articles.length);
      author.writeArticle( "test article" );
      assert.equal( 1 , author.articles.length);
    });
  });

  describe( "#listArticles" , function () {
    it( "should list articles" , function () {
      var author = new Author( "Jim" );
      author.writeArticle( "a great article" );
      assert.equal( "Jim has written: a great article" , author.listArticles());
    });
  });
});

现在,将test任务添加到package.json

"scripts": {
  "info": "echo 'npm as a build tool'",
  "lint": "echo '=> linting' && jshint assets/scripts/*.js",
  "test": "echo '=> testing' && mocha test/"
}

npm有一些方便的快捷方式,即npm testnpm startnpm stop 。 这些都是它们的run等效项的别名,这意味着我们只需要运行npm test来使摩卡付诸行动:

$ npm test -s
=> testing

  Author
    constructor
      ✓ should have a default name
    #writeArticle
      ✓ should store articles
    #listArticles
      ✓ should list articles

  3 passing ( 5 ms)

前后挂钩

如果我们要运行测试套件,并且由于语法错误而立即将其保释,那将不是很有效。 幸运的是,npm为我们提供了pre挂钩和post挂钩,因此,如果您运行npm run test ,它将在完成时首先执行npm run pretestnpm run posttest 。 在这种情况下,我们要在test脚本之前运行lint脚本。 以下pretest脚本使这成为可能。

"scripts" : {
  " info ": "echo 'npm as a build tool'" ,
  " lint ": "echo '=> linting' && jshint assets/scripts/*.js" ,
  " test ": "echo '=> testing' && mocha test/" ,
  " pretest ": "npm run lint -s"
 }

想象一下,以前我们没有纠正脚本中的语法错误。 在这种情况下,上述pretest脚本将因非零退出代码而失败,并且test脚本将无法运行。 这正是我们想要的行为。

$ npm test -s
=> linting
assets/scripts/main.js: line 1 , col 1 , Use the function form of "use strict" .
...
6 errors

使用main.js的更正代码:

=> linting
=> testing

  Author
    constructor
      ✓ should have a default name
    #writeArticle
      ✓ should store articles
    #listArticles
      ✓ should list articles

  3 passing ( 6 ms)

我们是绿色的!

代码压缩

在本节中,我们需要将dist目录以及几个子目录和文件添加到我们的项目中。 文件夹结构如下所示:

   ├── dist
   │   └── public
   │       ├── css
   │       ├── index .html
   │       └── js

在Unix机器上重新创建此命令的命令是:

mkdir -p dist/public/css dist/public/js && touch dist/public/index.html

index.html的内容很简单。

<!DOCTYPE html>
< html >
  < head >
    < meta charset = "utf-8" />
    < title > npm as a build tool </ title >
    < link href = 'css/main.min.css' rel = 'stylesheet' >
  </ head >
  < body >
    < h2 > npm as a build tool </ h2 >
    < script src = 'js/main.min.js' > </ script >
  </ body >
</ html >

当前main.js尚未缩小。 这是应该的,因为它是我们正在处理的文件,我们需要能够读取它。 但是,在将其上传到实时服务器之前,我们需要减小其大小并将其放置在dist/public/js目录中。 为此,我们可以安装uglify-js软件包并创建一个新脚本。

$ npm install uglify-js --save-dev

现在,我们可以在package.json创建一个新的minify:js脚本:

"scripts" : {
  " info ": "echo 'npm as a build tool'" ,
  " lint ": "echo '=> linting' && jshint assets/scripts/*.js" ,
  " test ": "echo '=> testing' && mocha test/" ,
  " minify:js ": "echo '=> minify:js' && uglifyjs assets/scripts/main.js -o dist/public/js/main.min.js" ,
  " pretest ": "npm run lint -s"
 }

运行:

$ npm run minify:js -s
=> minify:js

脚本会在正确的目标位置创建文件的缩小版本。 我们将使用clean-css包对CSS文件执行相同的操作。

$ npm install clean-css --save-dev

并创建minify:css脚本。

"scripts" : {
  " info ": "echo 'npm as a build tool'" ,
  " lint ": "echo '=> linting' && jshint assets/scripts/*.js" ,
  " test ": "echo '=> testing' && mocha test/" ,
  " minify:js ": "echo '=> minify:js' && uglifyjs assets/scripts/main.js -o dist/public/js/main.min.js" ,
  " minify:css ": "echo '=> minify:css' && cleancss assets/css/main.css -o dist/public/css/main.min.css" ,
  " pretest ": "npm run lint -s"
 }

让我们run脚本。

$ npm run minify:css -s
=> minify:css

留意变化

Grunt,Gulp和他们的同龄人最擅长的事情之一是,观察一组文件,并在检测到其中任何一个文件已更改时重新运行特定任务。 这在诸如此类的情况下特别有用,因为手动重新运行缩小脚本会很麻烦。

好消息是,您也可以在npm中使用watch这样的软件包来执行此操作,该软件包旨在使对文件和目录树的监视的管理更加容易。

$ npm install watch --save-dev

然后在package.json中,您需要指定检测到更改时要运行的任务。 在这种情况下,JavaScript和CSS最小化:

"scripts" : {
  ...
  " watch ": "watch 'npm run minify:js && npm run minify:css' assets/scripts/ assets/css/"
 }

使用以下命令启动脚本:

$ npm run watch

现在,每当assets/scripts/assets/css/任何文件更改时,都会自动调用缩小脚本。

构建脚本

到现在为止,我们已经可以将几个脚本链接在一起以创建一个build脚本,该脚本应该执行以下操作:整理,测试和缩小。 毕竟,一次又一次地单独运行这些任务会很痛苦。 要创建此构建脚本,请更改package.json的脚本对象,从而:

"scripts" : {
  " info ": "echo 'npm as a build tool'" ,
  " lint ": "echo '=> linting' && jshint assets/scripts/*.js" ,
  " test ": "echo '=> testing' && mocha test/" ,
  " minify:js ": "echo '=> minify:js' && uglifyjs assets/scripts/main.js -o dist/public/js/jquery.min.js" ,
  " minify:css ": "echo '=> minify:css' && cleancss assets/css/main.css -o dist/public/css/main.min.css" ,
  " build ": "echo '=> building' && npm run test -s && npm run minify:js -s && npm run minify:css -s" ,
  " pretest ": "npm run lint -s"
 }

运行build脚本将为我们提供以下输出。

$ npm run build -s
=> building
=> linting
=> testing

  Author
    constructor
      ✓ should have a default name
    #writeArticle
      ✓ should store articles
    #listArticles
      ✓ should list articles

  3 passing ( 6 ms)

=> minify:js
=> minify:css

服务器脚本

运行build脚本后,如果可以在dist启动内容服务器并在浏览器中进行检查,那就太好了。 我们可以使用http-server软件包来做到这一点。

$ npm install http-server -save-dev

我们制作一个server脚本。

"scripts" : {
  ...
  " server ": "http-server dist/public/" ,
}

现在我们可以run服务器了。

$ npm run server
Starting up http-server, serving dist/public/ on: http://0.0.0.0:8080
Hit CTRL-C to stop the server
_

当然可以将server脚本添加到build脚本中,但是我将其作为练习留给读者。

结论

希望本文已经证明npm作为构建工具可以多么灵活和强大。 下次启动新项目时,请尽量不要直接使用Gulp或Grunt等工具-尝试仅使用npm来解决您的需求。 您可能会感到惊喜。

如果您有任何问题或意见,我们很高兴在下面的帖子中听到。

From: https://www.sitepoint.com/guide-to-npm-as-a-build-tool/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值