作为现代开发人员,我们可以获得越来越多的工具来提高我们开发的速度和效率,也许Node.js和其他JavaScript后端工具日益受欢迎的最具影响力的因素之一是,它们允许我们在开发的每个阶段使用熟悉的语法。
例如,Taskrunners是专门用于自动化开发过程的各个方面的程序,有各种非常有用的JavaScriptTaskrunners和Build工具,如 Grunt.js, Gulp和 webpack。
让我们来看看我们可以使用的各种方法 npm 脚本来支持我们的开发需求。
标签:JSON
Node 中的每个项目都有一个 package.json 文件,其中包含有关该项目的元数据。在这个文件中,我们可以找到类似标题、描述、版本和依赖的内容。 该文件的主要目的是允许我们在 npm 上发布我们的项目。 当有人想从 npm 安装我们的程序时,他们的系统需要知道我们的其他程序要正确运行的内容。 它还需要知道关于程序的行为和配置的某些事情。
一个典型的 package.json 文件可能看起来如下:
1{
2 "name": "Crispy",
3 "version": "1.0.0",
4 "description": "Cooked to perfection!",
5 "main": "index.js",
6 "scripts": {
7 "test": "mocha"
8 },
9 "author": "AlligatorIO",
10 "license": "ISC",
11 "dependencies": {
12 "ws": "^3.3.2"
13 },
14 "devDependencies": {
15 "webpack": "^3.8.1"
16 }
17}
正如你所看到的,它只是一个包含与我们的项目相关信息的JSON对象的文件。
其中一个信息是脚本
部分,这些脚本是在开发和发布生命周期中在不同时刻触发的命令,其中最常见的 npm 脚本是开始
脚本和测试
脚本,在上一个例子中你会注意到没有定义开始脚本,因为 npm 具有开始脚本的默认值,即node server.js
。这意味着如果我们不选择定义我们自己的自定义开始脚本,在命令行中键入npm start
,将自动搜索名为 server.js 的文件,并在 Node 中运行该文件。
请注意,我们的测试
脚本的值只是mocha
。 Mocha是一个常见的JavaScript测试工具包,一旦安装,它可以简单地使用命令行中的mocha
命令运行。
有许多不同的 npm 脚本涵盖广泛的用例,但我们目前最感兴趣的是我们可以使用这些脚本在开发新项目时使我们的生活更容易的方式。
了解生命周期
解锁npm脚本的第一个关键是了解npm在运行脚本时正在做什么。它做的第一件事是检查 package.json文件,看看您是否为该脚本定义了值。如果它发现您有,那么它会寻找另外两个版本的脚本。
例子:
1{
2 "scripts": {
3 "prestart": "node loadJaw.js",
4 "start": "node Gator.js",
5 "poststart": "node bite.js"
6 }
7}
如果这是 npm 在我们的 package.json 文件中找到的,它会以重新启动
、启动
、后启动
的顺序运行脚本,然后是后启动
。我们所要做的就是在命令行中键入npm 启动
。这对于各种情况非常有用,您需要在主要操作之前或之后立即发生某些事情。
如果我们正确设置我们的脚本,那么简单地运行npm start
命令将能够以正确的顺序处理所有我们的需求。
开发模式 vs 生产模式
使用 npm 脚本最有用的方法之一是改变 Node 的 Node_ENV
变量值,它可以在任何 Node 程序中通过全球过程变量访问。
1function getEnvironment(){
2 return process.env.Node_ENV;
3}
4
5getEnvironment(); // returns 'production';
许多框架使用Node_ENV
变量值来确定是否在开发模式或生产模式中运行。区别在于,生产模式往往是优化的性能,而作为开发模式是优化的调试。
例如,想象一下,我们想要登录访问者到我们的网站。在生产模式中,我们可能只是想登录每个新访问者的IP地址到日志文件,以便稍后进行参考。在开发模式中,我们可能正在实时分析流量以排除错误,所以我们希望登录有关新访问者的信息到不同的文件,以及登录流量到控制台,以便我们可以观看它发生时。
1const fs = require('fs');
2const inDevelopmentMode = process.env.Node_ENV === development;
3
4function newVisitor(ip){
5 let logMessage = "New Visitor IP: " + ip;
6
7 if(inDevelopmentMode){
8 fs.writeFile("development_log.txt", logMessage, (err) => {
9 if(err) throw err;
10 });
11 console.log(logMessage);
12 }
13 else{
14 fs.writeFile("production_log.txt", logMessage, (err) => {
15 if(err) throw err;
16 });
17 }
18}
在这里,我们正在使用 fs 模块与我们的文件系统进行交互。我们正在引用 Node_ENV
变量来确定我们是否处于开发模式,如果是这样,则会登录到 development_log.txt 文件和控制台。
但是,我们如何真正改变Node_ENV
变量?一种方法是使用npm脚本!在我们的package.json文件中:
1{
2 "scripts": {
3 "start": "SET Node_ENV=development& node server.js",
4 }
5}
语法可能看起来有点有趣,并在第一眼提起一些问题. 这里有一个解释为什么它是这样做的. 有几个重要但不可预测的事情要注意,当尝试这样做。
- 将 Node_ENV 变量设置为其他步骤,而不是与它进行交互的步骤,可能会导致错误。 这是因为每次运行 npm 脚本,它被认为是另一个
过程
。 如果我们在prestart
脚本中更改 Node_ENV 值,它不会转移到start
脚本流程,所以我们必须在start
脚本中更改它,如果我们打算在我们的 server.js 文件中与它进行交互 - Linux 和 Windows 处理变量更改的方式之间有轻微的差异。 在 Linux 中,你可以忽略
SET
命令,然后简单地使用Node_ENV=development& node server.js
。 在 Windows 中,你必须使用SET
当然,Linux和Windows设置环境变量的方式之间的差异可能会导致不兼容性,如果一个团队正在从两种操作系统中开发一个项目。有几种方法可以处理这一点。你可以使用一个脚本或模块,例如(Cross-env)(https://www.npmjs.com/package/cross-env),试图在运行命令之前确定程序在运行哪个操作系统上运行,或者你可以为每个操作系统使用不同的npm脚本,并让开发人员记住使用哪个。
任意写作
幸运的是,npm 提供了通过允许我们定义我们自己的自定义任意脚本的方式来实现这一点,我们可以将这些脚本命名为我们想要的任何东西,并且 npm 仍然会像我们预期的那样运行它们。它仍然会尝试在触发时运行脚本的所有生命周期变异,通过将预先
和邮件
提交给我们提供的名称。这使我们能够在开发过程中使用任何数量的自定义脚本。
对于每个受支持的 npm 脚本,我们输入npm <script-name>
,要触发任意脚本,我们需要使用npm run <script-name>
。
如果我们想要一个自定义的脚本来启动本地MongoDB实例,我们可以这样做:
1{
2 "scripts": {
3 "start": "SET Node_ENV=development& node server.js",
4 "mongo": "mongod --dbpath=./pathToDatabase/db"
5 }
6}
现在我们可以使用npm run mongo
来启动数据库。
任意脚本非常适合随意触发不同的命令序列,例如:
1{
2 "scripts": {
3 "test": "mocha",
4 "start": "SET Node_ENV=development& node server.js",
5 "mongo": "mongod --dbpath=./pathToDatabase/db",
6 "launch": "npm test && npm run mongo && npm start",
7 }
8}
在这里,我们有一个启动脚本,触发我们的测试,mongo,并在这个顺序下启动脚本。
1{
2 "scripts": {
3 "start": "concurrently \"node grip.js bacon\" \"node bite.js bacon\""
4 }
5}
最后的想法
希望读到这篇文章能给你一些关于如何利用 npm 脚本来帮助你的开发工作流程的想法!我个人更喜欢我的开始
脚本触发一个生产环境,并创建一个任意的dev
脚本触发一个开发环境。