为REST API设置节点环境 - 我的头发变灰了

时间:2021-11-20 23:24:16

I am being very humble here coming to the community. I don't know jack about node environments yet, as well as am the only Node developer here. A one man team right now for building out my first Node REST API. (yea, really what we need are more people who already know a bit more Node than I to help this learning process along).

我来这个社区非常谦虚。我还不知道关于节点环境的插孔,以及这里唯一的Node开发人员。现在是一个单人团队,用于构建我的第一个Node REST API。 (是的,我们真正需要的是那些已经比我知道更多节点的人来帮助这个学习过程)。

I've searched endlessly for hours on the web to try and do my due diligence..but frankly I'm just not finding much out there on setting up Node.js environments as well as setting up local vs. other environmental builds. First just starting with setting up a local build - baby steps is all I'm looking for... in a real world scenario. Most blog posts show the simplest development environment only at best. And so to make matters even worse, most the blog posts talk about website setup (browsify sh__ and stuff like that). I'm doing a REST API, not a website here.

我在网上无休止地搜索了几个小时来尝试做我的尽职调查。但坦率地说,我在设置Node.js环境以及设置本地与其他环境构建方面并没有太多发现。首先从设置本地构建开始 - 我正在寻找婴儿步骤...在现实世界中。大多数博客帖子只展示了最简单的开发环境。所以更糟糕的是,大多数博客文章谈论网站设置(browsify sh__和类似的东西)。我正在做一个REST API,而不是这里的网站。

I need some resources to start with which either I'm just not searching right for them for node or they just are that hard to find. I want really a walk through of how you'd set your environment variables, how you'd use gulp with those variables to run different environment situations, and how people are managing their persistent layer stuff like database connection strings, etc...which I assume is also automated in part by gulp tasks reading config files that contain the connection strings? I'm really not sure, there are not a lot of good examples out there..

我需要一些资源来开始,或者我只是不为他们寻找节点,或者他们只是很难找到。我想深入了解你如何设置环境变量,如何使用gulp与这些变量运行不同的环境情况,以及人们如何管理持久层事物,如数据库连接字符串等...我假设也通过gulp任务自动读取包含连接字符串的配置文件?我真的不确定,那里没有很多好的例子..

Which is why I'm here to hopefully find some this route, by posting this here. (and hopefully comments on my current gulpfile...is it way f'd up or not even close to the right track or where the hell should I start for the build and environment conventions and tasks?)

这就是为什么我在这里希望找到这条路线,在这里张贴。 (并且希望对我当前的gulpfile发表评论......是否可以提升或者不接近正确的轨道,或者我应该从哪里开始构建和环境约定和任务?)

What would be nice is to find a good posts that walk you through a day in the life of a node developer.

最好的方法是在节点开发人员的生活中找到一篇能够引导您度过一天的好帖子。

Where am I at Currently?

我现在在哪里?

My API: Well I've build out a few Koa.js endpoints, I've got some controllers that take in the request, process it by using a gateway node modules I've guilt that have some CRUD persistence methods in what I call a gateway layer which calls underlying set of Model classes which mean the real CRUD calls to a real DB and some mocks for my tests, etc. Very basic at this point...all test driven via Mocha.js (BDD style).

我的API:我已经构建了一些Koa.js端点,我有一些接收请求的控制器,通过使用网关节点模块来处理它我感到内疚,在我所说的内容中有一些CRUD持久性方法一个网关层调用底层的Model类集合,这意味着真正的CRUD调用真实数据库,一些模拟测试等等。此时非常基本...所有测试都是通过Mocha.js(BDD风格)驱动的。

My Day: So right now, I come into work, I have already setup my mocha.js test environment and I'm able to at least test drive development of my code and have tests run nicely on saves. I can watch my files and my tests run with mocha reports in the terminal. My app runs, all that.

我的日子:所以现在,我开始工作,我已经设置了我的mocha.js测试环境,我至少可以测试我的代码的驱动开发,并且测试运行得很好。我可以观看我的文件,我的测试在终端中使用mocha报告运行。我的应用程序运行,所有这些。

My Problem: But I really haven't automated this much other than that via gulp. I wanna know more about setting up environment variables, what a developer would do when he/she's ready to build and push to git, yada yada and then ultimately how to switch environments, the motions of doing that when pushing to other servers, and all that via whatever configuration or gulp tasks that would facilitate this. I just need a good example of this kinda ecosystem. Any kind of example but something realistic would be so damn helpful.

我的问题:但是我真的没有通过gulp进行自动化。我想知道更多关于设置环境变量的信息,开发人员在他/她准备构建和推送到git,yada yada然后最终如何切换环境时会做什么,在推送到其他服务器时这样做的动作,以及所有通过任何可以促进这一点的配置或gulp任务。我只需要一个这种生态系统的好例子。任何一个例子,但现实的东西将是如此有用。

So...Here's a glimps of my current gulpfile. Now there is build stuff in there for the babel transpiler (yes I'm using ES6 to ES5 code in my js), but I got that from some other code but really haven't figure out how all this will work yet. Really the stuff I setup is my test run and automation at this point. The build stuff I kinda disabled because a) I don't really know which files should be part of the build for a REST API outside your app.js, server.js and b) the build code I grabbed from some code I found transpiles js files via babel into a build folder but then I get issues with code collision/conflicts with my regular code. For example that build stuff below was pushing server.js into a build folder and when I tried to run the regular server.js in the root, it was colliding with the code in build/server.js so this is all f'd up and obviously I don't know what the hell I should be doing yet with builds.

所以...这是我目前的gulp文件的一瞥。现在有针对babel转换器的构建内容(是的,我在我的js中使用ES6到ES5代码),但是我从其他代码中得到了这个但是真的还没弄清楚这一切是如何工作的。我设置的东西真的是我的测试运行和自动化。构建的东西我有点禁用,因为a)我真的不知道哪些文件应该是app.js,server.js之外的REST API构建的一部分,b)我从一些代码中抓取的构建代码我发现了js文件通过babel进入构建文件夹,但后来我遇到代码冲突/与我的常规代码冲突的问题。例如,下面的构建内容是将server.js推送到构建文件夹中,当我尝试在根目录中运行常规server.js时,它与build / server.js中的代码发生冲突,所以这就是f'd up显然我不知道我应该用构建做什么。

'use strict';

require('babel/register');
require("harmonize")();

var gulp = require('gulp'),
    mocha = require('gulp-mocha'),
    gutil = require('gulp-util'),
    babel = require("gulp-babel"),
    server = require('gulp-develop-server'),
    del = require('del');


var config = {
    core: {
        src: '*.js',
        build: {
            src: 'build'
        }
    },
    server: {
        path: ['app.js']
    },
    bs: {
        proxy: 'http://localhost:3000'
    },
    test:{
        root: 'test/**',
        src: {
            bdd: {
                features:'test/bdd/features/**/*-spec.js',
                unit:'test/bdd/unit/**/*-test.js',
                integration: 'test/bdd/integration/**/*-integration.js'
            }
        },
        mocha: {
            reporter: 'spec'
        }
    }
};

gulp.task('default', ['babel','development'], function(){
    gulp.task("watch", function(){
        gulp.watch('**/*.js', ['babel'])
    });
});

gulp.task('development',['mocha-bdd-features', 'mocha-bdd-unit'], function() {
    gulp.watch('**/*.js', ['mocha-bdd-features', 'mocha-bdd-unit']);
});

gulp.task('babel', function () {
    return gulp.src('./*.js')
        .pipe(babel());
        //.pipe(gulp.dest('build'));
});

gulp.task('build', ['clean'], function () {
});

gulp.task('clean', del.bind(
    null, ['build/*'], {dot: true}
));

gulp.task('server:start', function() {
    server.listen( { path: config.server.path});
});

gulp.task('server:restart', function() {
    server.restart();
});

gulp.task('mocha-bdd-features', function() {
    process.env.PORT = 8001;
    return gulp.src([config.test.src.bdd.features], { read: false })
        .pipe(mocha({
            compilers: {
                js: babel
            },
            reporter: config.test.mocha.reporter,
            ui: 'bdd'
        }))
        .on('error', gutil.log);
});

gulp.task('mocha-bdd-unit', function() {
    process.env.PORT = 8002;
    return gulp.src([config.test.src.bdd.unit], { read: false })
        .pipe(mocha({
            compilers: {
                js: babel
            },
            reporter: config.test.mocha.reporter,
            ui: 'bdd'
        }))
        .on('error', gutil.log);
});

gulp.task('mocha-bdd-integration', function() {
    process.env.PORT = 8003;
    return gulp.src([config.test.src.bdd.integration], { read: false })
        .pipe(mocha({
            compilers: {
                js: babel
            },
            reporter: config.test.mocha.reporter,
            ui: 'bdd'
        }))
        .on('error', gutil.log);
});

gulp.on('err', function(e) {
    console.log(e.err.stack);
});

my package.json scripts thus far:

到目前为止我的package.json脚本:

  "scripts": {
    "start": "gulp",
    "build": "gulp build", // I was running this for a while
    "release": "gulp build --release", //I haven't used this yet or know if I even will yet
// I definitely use these, I set these up myself
    "test-bdd-features": "gulp mocha-bdd-features",
    "test-bdd-unit": "gulp mocha-bdd-unit",
    "test-bdd-integration": "gulp mocha-bdd-integration"
  },

Basically as a developer the way I have my gulpfile right now is I type 'gulp' at the bash prompt (terminal from within Webstorm in my case) which runs the default gulp task, and then that first off a few more tasks at this point where a few things happen thus far:

基本上作为开发人员,我现在拥有gulpfile的方式是在bash提示符下键入'gulp'(在我的情况下是Webstorm中的终端),它运行默认的gulp任务,然后在此时首先关闭几个任务到目前为止发生了一些事情:

  1. it runs all my mocha tests on first run of gulp
  2. 它在第一次吞咽时运行我的所有摩卡测试

  3. watches all js files for mocha so that mocha tests run on save of any js code changes
  4. 监视mocha的所有js文件,以便在保存任何js代码更改时运行mocha测试

Really that's all that's going on. I can run the node server ok and all that too. But it's very basic at this point. I've got the stupid app.listen() port hard coded in my dumb app.js file which obviously is...well hard coded!

真的,这就是所有这一切。我可以运行节点服务器ok和所有这些。但在这一点上它是非常基本的。我有一个愚蠢的app.listen()端口硬编码在我的哑app.js文件中,显然是......很难编码!

And honestly I have different ports for my different test suites because I found I had to due to port conflicts but maybe that's just because of something weird I did, not sure if this is the norm to have diff ports for running your acceptance tests vs. unit but I'd assume so.

老实说,我的不同测试套件有不同的端口,因为我发现我不得不因为端口冲突,但也许这只是因为我做了一些奇怪的事情,不确定这是否是运行验收测试的差异端口的标准单位,但我会这样认为。

Ahhh!! Advil please!

唉唉!请高手!

So at this point I'm like pulling my hair out on how to get through this:

所以在这一点上,我喜欢把头发拉出来解决这个问题:

  1. how to setup a real build for a REST API (ok you transpile js code via babel to where, and what and huh?)
  2. 如何为REST API设置真正的构建(好吧你通过babel将js代码转移到哪里,以及什么呢?)

  3. the ecosystem for setting up tasks, configs, etc. for automating builds and pushing and running code in diff environments..what does that look like!
  4. 用于设置任务,配置等的生态系统,用于在差异环境中自动构建和推送和运行代码。这看起来像什么!

  5. The pulling down of code in different environments and running those and what not on different server scenarios (dev, QA, stage, prod).
  6. 在不同的环境中下载代码并在不同的服务器方案(dev,QA,stage,prod)上运行这些代码。

And because I know someone will respond with this for sure. Yes I understand "there are a million ways to do this". You're preaching to the choir. I get that but that's not the point here. I am asking for a lot of info here so feel free to pick and choose what to reply with to hopefully help get me in the right direction on builds or enviornments. I'm just asking for examples of ways period, or analysis of my gulp file, or just a place to start!...so I can understand generally the process people go through and what are typical task types run that do what in gulp, etc. and how environment variables are managed and what not typically in Node apps.

而且因为我知道有人肯定会对此作出回应。是的,我理解“有一百万种方法可以做到这一点”。你正在向合唱团讲道。我明白了,但这不是重点。我在这里要求提供大量信息,所以请随意选择要回复的内容,希望能帮助我在构建或环境方面找到正确的方向。我只是想问一下方式的例子,或者我的gulp文件的分析,或者只是一个开始的地方!...所以我通常可以理解人们经历的过程以及什么是典型的任务类型运行,做什么在gulp等等,以及如何管理环境变量以及Node应用程序中通常不具备的内容。

1 个解决方案

#1


2  

In my limited experience, I think the most beneficial thing I've learned so far with this build and config stuff ("sysadmin is why I drink") is to keep it as simple and composable as possible.

在我有限的经验中,我认为到目前为止我用这种构建和配置的东西(“系统管理员就是为什么我喝酒”)学到的最有益的事情就是让它尽可能简单和可组合。

Config info

For starters, if this helps at all, I'm a big fan of keeping config information is a .json and referencing that throughout the project. For example:

对于初学者来说,如果这有帮助的话,我非常喜欢保持配置信息是一个.json并在整个项目中引用它。例如:

// config.json
{
  "STAGING": "http://staging.yourdomain.com/api/",
  "PRODUCTION": "http://yourdomain.com/api/",
  "THE_BEST_PORT_EVER": 1337,
  "MY_DOGS_NAME": "Ginger"
}

This is that whole "magic string" avoidance thing, so you have just one place to reference all your pertinent environment information.

这就是整个“神奇的字符串”避免的事情,所以你只有一个地方可以引用你所有相关的环境信息。

In your gulpfile, when you need to reference some URL, or some port, or just whatever, you just require it:

在你的gulp文件中,当你需要引用某个URL或某个端口,或者只是需要它时,你只需要它:

var config = require('config.json');

Test stuff

There's a 1,000 ways to do it... I'm not familiar with the current setup you have, but if it works it works. However, I will caveat that with, try to keep things as modular as possible (as in, even if the functions look like crap, at least they're all independent of each other... read: function composition.)

有1000种方法可以做到这一点......我对你目前的设置并不熟悉,但是如果它有效则可行。但是,我会注意到,尽量保持模块尽可能模块化(例如,即使函数看起来像垃圾,至少它们都是彼此独立的......阅读:函数组合。)

Building for different environments

I hate long, obfuscated gulpfiles. Currently, my team is working on various distinct web and mobile applications, and various iterations of static sites, all for one product. All of which need to be tracked in version control for various environments, and built and deployed to various environments. However, our build processes are relatively simple, I hope (though they could definitely be improved).

我讨厌长期混淆的gulpfiles。目前,我的团队正在开发各种不同的Web和移动应用程序,以及各种静态站点的迭代,所有这些都针对一种产品。所有这些都需要在各种环境的版本控制中进行跟踪,并构建和部署到各种环境。但是,我希望我们的构建过程相对简单(虽然它们肯定可以改进)。

I like gulpfiles that look like this:

我喜欢看起来像这样的gulpfiles:

// all your require'd stuff

// this is helpful, 'cause you can do stuff like "gulp --production"
var argv = require('yargs').argv;

var paths = {
  sass: ['some/path/to/sass'],
  // various other paths
};

gulp.task('sass', compileSass);
gulp.task('html', html);
gulp.task('default', watch);
// etc.

// then, in pretty alphabetical order
function compileSass() {
  return gulp.src(paths.sass)
         .pipe(doSomeCoolStuff());
}

function html() {
  // etc.
}

function watch() {
  compileSass();
  html();

  if(argv.production) {
    someSpecificProductionFunction();
  }

  gulp.watch(paths.someAwesomePaths, ['someTask']);
}

I like gulpfiles that look like that, because they're compositional.

我喜欢看起来像这样的gulpfiles,因为它们是组合的。

As far as building goes, I don't even worry about defining package.json scripts. Could you? Sure. I guess it depends on the project and matters of personal/team style, but for the projects we're doing, at the moment there's no benefit to add an additional layer of abstraction. Why run something like npm doSomething, which is just an alias for ./some-script, which is just an alias for, say, gulp --production?

就构建而言,我甚至不担心定义package.json脚本。你可以吗?当然。我想这取决于项目和个人/团队风格的问题,但对于我们正在进行的项目,目前添加额外的抽象层没有任何好处。为什么运行像npm doSomething这样的东西,它只是./some-script的别名,这只是gulp --production的别名?

Here's an excerpt from a README we have for an app:

以下是我们为应用程序提供的README的摘录:

Case 1

I want to run the app in my browser hitting my local server

我想在我的浏览器中运行应用程序命中我的本地服务器

Make sure your config-local.json matches config-example.json, but with your local server (something like http://your.ip.here:1337/api/). Make sure you have the most recent version of the server installed and running. The run ionic serve.

确保config-local.json与config-example.json匹配,但与本地服务器匹配(如http://your.ip.here:1337/api/)。确保已安装并运行最新版本的服务器。运行离子发球。

Case 2

I want to run the app in my browser hitting a different server.

我想在我的浏览器中运行应用程序命中另一台服务器。

Change the server address in your config-local.json and follow Case 1.

更改config-local.json中的服务器地址,然后按照案例1进行操作。

Case 3

I want to run the app on a device in a complete staging environment.

我想在完整的暂存环境中在设备上运行应用程序。

Run gulp --staging. Then run ionic run --device.

运行gulp --staging。然后运行离子运行 - 设备。

Case 4

I want to run the app on a device in a complete production environment.

我想在完整的生产环境中在设备上运行应用程序。

Run gulp --production. Then run ionic run --device.

运行gulp --production。然后运行离子运行 - 设备。

A lot of time is spent working on "how do I make this easier for the user?" But what about the question, "how do I make this easier for the developer?"

花了很多时间研究“我如何让用户更轻松?”但问题是,“我如何让开发人员更容易?”

The fewer steps involved in a build process means that they're are fewer points of failure when trying to build.

构建过程中涉及的步骤越少意味着在构建过程中它们的失败点就越少。

That also means that your code needs to be as small as possible. 10 solutions might have the same outcome, but 9 of those solution might be crap.

这也意味着您的代码需要尽可能小。 10个解决方案可能会有相同的结果,但其中9个解决方案可能是废话。

#1


2  

In my limited experience, I think the most beneficial thing I've learned so far with this build and config stuff ("sysadmin is why I drink") is to keep it as simple and composable as possible.

在我有限的经验中,我认为到目前为止我用这种构建和配置的东西(“系统管理员就是为什么我喝酒”)学到的最有益的事情就是让它尽可能简单和可组合。

Config info

For starters, if this helps at all, I'm a big fan of keeping config information is a .json and referencing that throughout the project. For example:

对于初学者来说,如果这有帮助的话,我非常喜欢保持配置信息是一个.json并在整个项目中引用它。例如:

// config.json
{
  "STAGING": "http://staging.yourdomain.com/api/",
  "PRODUCTION": "http://yourdomain.com/api/",
  "THE_BEST_PORT_EVER": 1337,
  "MY_DOGS_NAME": "Ginger"
}

This is that whole "magic string" avoidance thing, so you have just one place to reference all your pertinent environment information.

这就是整个“神奇的字符串”避免的事情,所以你只有一个地方可以引用你所有相关的环境信息。

In your gulpfile, when you need to reference some URL, or some port, or just whatever, you just require it:

在你的gulp文件中,当你需要引用某个URL或某个端口,或者只是需要它时,你只需要它:

var config = require('config.json');

Test stuff

There's a 1,000 ways to do it... I'm not familiar with the current setup you have, but if it works it works. However, I will caveat that with, try to keep things as modular as possible (as in, even if the functions look like crap, at least they're all independent of each other... read: function composition.)

有1000种方法可以做到这一点......我对你目前的设置并不熟悉,但是如果它有效则可行。但是,我会注意到,尽量保持模块尽可能模块化(例如,即使函数看起来像垃圾,至少它们都是彼此独立的......阅读:函数组合。)

Building for different environments

I hate long, obfuscated gulpfiles. Currently, my team is working on various distinct web and mobile applications, and various iterations of static sites, all for one product. All of which need to be tracked in version control for various environments, and built and deployed to various environments. However, our build processes are relatively simple, I hope (though they could definitely be improved).

我讨厌长期混淆的gulpfiles。目前,我的团队正在开发各种不同的Web和移动应用程序,以及各种静态站点的迭代,所有这些都针对一种产品。所有这些都需要在各种环境的版本控制中进行跟踪,并构建和部署到各种环境。但是,我希望我们的构建过程相对简单(虽然它们肯定可以改进)。

I like gulpfiles that look like this:

我喜欢看起来像这样的gulpfiles:

// all your require'd stuff

// this is helpful, 'cause you can do stuff like "gulp --production"
var argv = require('yargs').argv;

var paths = {
  sass: ['some/path/to/sass'],
  // various other paths
};

gulp.task('sass', compileSass);
gulp.task('html', html);
gulp.task('default', watch);
// etc.

// then, in pretty alphabetical order
function compileSass() {
  return gulp.src(paths.sass)
         .pipe(doSomeCoolStuff());
}

function html() {
  // etc.
}

function watch() {
  compileSass();
  html();

  if(argv.production) {
    someSpecificProductionFunction();
  }

  gulp.watch(paths.someAwesomePaths, ['someTask']);
}

I like gulpfiles that look like that, because they're compositional.

我喜欢看起来像这样的gulpfiles,因为它们是组合的。

As far as building goes, I don't even worry about defining package.json scripts. Could you? Sure. I guess it depends on the project and matters of personal/team style, but for the projects we're doing, at the moment there's no benefit to add an additional layer of abstraction. Why run something like npm doSomething, which is just an alias for ./some-script, which is just an alias for, say, gulp --production?

就构建而言,我甚至不担心定义package.json脚本。你可以吗?当然。我想这取决于项目和个人/团队风格的问题,但对于我们正在进行的项目,目前添加额外的抽象层没有任何好处。为什么运行像npm doSomething这样的东西,它只是./some-script的别名,这只是gulp --production的别名?

Here's an excerpt from a README we have for an app:

以下是我们为应用程序提供的README的摘录:

Case 1

I want to run the app in my browser hitting my local server

我想在我的浏览器中运行应用程序命中我的本地服务器

Make sure your config-local.json matches config-example.json, but with your local server (something like http://your.ip.here:1337/api/). Make sure you have the most recent version of the server installed and running. The run ionic serve.

确保config-local.json与config-example.json匹配,但与本地服务器匹配(如http://your.ip.here:1337/api/)。确保已安装并运行最新版本的服务器。运行离子发球。

Case 2

I want to run the app in my browser hitting a different server.

我想在我的浏览器中运行应用程序命中另一台服务器。

Change the server address in your config-local.json and follow Case 1.

更改config-local.json中的服务器地址,然后按照案例1进行操作。

Case 3

I want to run the app on a device in a complete staging environment.

我想在完整的暂存环境中在设备上运行应用程序。

Run gulp --staging. Then run ionic run --device.

运行gulp --staging。然后运行离子运行 - 设备。

Case 4

I want to run the app on a device in a complete production environment.

我想在完整的生产环境中在设备上运行应用程序。

Run gulp --production. Then run ionic run --device.

运行gulp --production。然后运行离子运行 - 设备。

A lot of time is spent working on "how do I make this easier for the user?" But what about the question, "how do I make this easier for the developer?"

花了很多时间研究“我如何让用户更轻松?”但问题是,“我如何让开发人员更容易?”

The fewer steps involved in a build process means that they're are fewer points of failure when trying to build.

构建过程中涉及的步骤越少意味着在构建过程中它们的失败点就越少。

That also means that your code needs to be as small as possible. 10 solutions might have the same outcome, but 9 of those solution might be crap.

这也意味着您的代码需要尽可能小。 10个解决方案可能会有相同的结果,但其中9个解决方案可能是废话。