JavaScript 项目设置指南

注意

我们支持 Ubuntu LTS 版本中可用的当前版本的 node.js 和 npm。 截至撰写本文时,这些是 Node v0.10.29 和 npm v1.4.21。 使用较新的版本可能会产生意想不到的结果。

快速入门

这些是 OpenStack JavaScript 项目的通用项目设置说明。 个人项目可以扩展或覆盖这些说明,因此请检查其他文档。

安装依赖项

在 OSX (使用 homebrew)

brew install nodejs

注意

Homebrew 无法轻松安装我们支持的版本的 node.js 和 npm。 上面似乎兼容,但仍可能发生意想不到的结果。

在 Debian 上

# Using Ubuntu
sudo curl -sL https://deb.nodesource.com/setup_0.10 | sudo -E bash -
sudo apt-get install -y nodejs

# Using Debian
sudo curl -sL https://deb.nodesource.com/setup_0.10 | sudo bash -
sudo apt-get install -y nodejs

在 CentOS 上

sudo curl -sL https://rpm.nodesource.com/setup | bash -
sudo yum install -y nodejs

检出并初始化项目

所有项目初始化和虚拟环境创建都通过 npm 处理。 此过程非常简单,将确保所有依赖项、工具和其他资源可用。

# Check out the project
git checkout https://git.openstack.org/openstack/<PROJECT NAME>.git

# Initialize the project.
cd <PROJECT NAME>
npm install

测试代码库

初始化后,您应该能够运行一些基本测试。

npm run lint

这将运行我们的代码风格检查。

npm test

这将运行测试并报告测试覆盖率。

npm start

对于基于 Web 的项目,此命令应启动服务器。

常用工具

以下部分讨论了《一致测试接口》中规定的每个命令,包括相同的工具和设置说明。

代码风格检查

命令

npm run lint

OpenStack 需要自定义 npm 脚本“lint”来执行我们的代码风格检查。 我们使用的工具称为 ESLint,我们的规则发布到 npm 作为 eslint-config-openstack。 要使用这些规则初始化您的项目,请在项目根目录中执行以下步骤。

首先,将 eslint 和 eslint-config-openstack 添加到您的项目,并初始化一个基本的 .eslintrc 文件。

npm install --save-dev eslint eslint-config-openstack
echo "extends: openstack" > .eslintrc

其次,将 lint 脚本添加到您的 project.json 文件

{
  ...
  'scripts' : {
    'lint': 'eslint ./'
  },
  ...
}

有关如何排除文件、覆盖特定规则或规则本身的更多信息,请访问 ESLint 项目。 如果您想为 OpenStack 的 ESLint 规则做出贡献,可以在 eslint-config-openstack 上进行贡献。

执行测试和覆盖率

命令

npm test

OpenStack 需要为每个项目制定合理的测试和代码覆盖率策略,但我们不规定工具和覆盖率阈值,因为这些可能因情况和项目类型而异。 生成的测试报告应放置在您项目的根目录中的 ./reports 中。 生成的覆盖率输出应类似地放置在 ./cover 中。

浏览器项目的示例设置,使用 Karma、Jasmine 和 Istanbul。

// ./package.json
{
  ...
  "scripts": {
    ...
    "test": "karma start ./karma.conf.js",
    ...
  },
  "devDependencies": {
    ...
    "jasmine": "2.3.2",
    "karma": "0.13.9",
    "karma-chrome-launcher": "0.2.0",
    "karma-cli": "0.1.0",
    "karma-coverage": "0.5.0",
    "karma-firefox-launcher": "0.1.6",
    "karma-jasmine": "0.3.6",
    "karma-phantomjs-launcher": "0.2.1",
    "karma-threshold-reporter": "0.1.15",
    ...
  }
}

// ./karma.conf.js
module.exports = function (config) {
  config.set({
    'frameworks': ['jasmine'],
    'browsers': ['PhantomJS', 'Chrome', 'Firefox'],
    'reporters': ['progress', 'coverage', 'threshold'],

    'plugins': [
      'karma-jasmine',
      'karma-coverage',
      'karma-threshold-reporter',
      'karma-phantomjs-launcher',
      'karma-chrome-launcher',
      'karma-firefox-launcher'
    ],

    'preprocessors': {
      'www/js/{!lib/**/*.js,*.js}': ['coverage']
    },

    'files': [
      // Library files, with some ordering.
      'www/js/lib/angular.js',
      'node_modules/angular-mocks/angular-mocks.js',
      'www/js/lib/*.js',

      // Application files
      'www/js/**/*.js',

      // Tests
      'test/js/**/*.js'
    ],

    'coverageReporter': {
      type: 'html',
      dir: 'cover',
      instrumenterOptions: {
        istanbul: {noCompact: true}
      }
    },

    // Coverage threshold values.
    thresholdReporter: {
      statements: 100,
      branches: 100,
      functions: 100,
      lines: 100
    },
    'singleRun': true
  });
};

Node.js 项目的示例设置,使用 Jasmine 和 Istanbul

# /package.json
{
  ...
  "scripts": {
    "test": "istanbul cover --print=detail --include-all-sources jasmine",
    ...
  },
  ...
  "devDependencies": {
    ...
    "istanbul": "0.3.17",
    "jasmine": "2.3.1",
    ...
  }
}

# /spec/support/jasmine.json
{
  "spec_dir": "spec",
  "spec_files": [
    "**/*.js",
    "!helpers/**/*.js"
  ],
  "helpers": [
    "helpers/**/*.js"
  ]
}

包 tarball 生成

命令

npm pack

OpenStack 使用 npm pack 生成发布 tarball,它将编译 package.json 中列出的所有文件。 如果您的项目需要连接、缩小或其他预处理来创建有效的 tarball,您可以使用 npm prepublish 钩子来触发这些步骤。

一个示例 package.json 文件可能如下所示。

{
  ...
  'scripts': {
    'prepublish': 'uglify -s ./src/**/*.js -o ./lib/generated.min.js'
  },
  files: [
    'LICENSE',
    'README.md',
    'index.js',
    'lib/*.js'
  ],
  ...
}

所有包应包括

  • 一个 README

  • 一个 LICENSE 文件

  • 所有源代码

生成文档

命令

npm run document

尚未讨论为 JavaScript 项目生成文档的规范方法。 如果您想做出贡献,请加入 OFTC 中的 #openstack-docs 或 #openstack-javascript 的对话。

验证依赖项许可证

命令

npm run document

尚未讨论验证依赖项许可证的常用方法。 如果您想做出贡献,请加入 OFTC 中的 #openstack-javascript 的对话。

导入翻译字符串

命令

npm run translate

尚未讨论为 JavaScript 项目导入翻译的规范方法。 如果您想做出贡献,请加入 OFTC 中的 #openstack-i18n 和 #openstack-javascript 的对话。

最佳实践

通用项目设置指南中概述的所有最佳实践适用于 JavaScript 项目。 以下是一些额外的建议。

使用工具,而不是适配器

本节特别针对 gulp、grunt 和类似的构建工具,它们旨在将所有构建步骤统一到一个屋檐下。 虽然有用,但它们通常通过包装已经存在的工具来实现这一点,同时添加自己的依赖项。 为了避免这种膨胀 - 以及潜在的跨依赖版本不匹配 - 直接使用工具比维护额外的抽象层更容易。

示例:* 使用 eslint 代替 gulp-eslint * 使用 karma 代替 grunt-karma * 使用 webpack 代替 gulp-webpack

不要缩小

缩小是一种常用的优化步骤,它以牺牲可读性为代价来减小 JavaScript 文件大小。 虽然此步骤通常可以提供显着的负载减少,尤其是在与 HTTP GZip 压缩和 HTTP 缓存标头结合使用时,但我们更喜欢将此决定权交给操作员。

不要使用模糊版本

package.json 或 bower.json 中声明的依赖项使用模糊版本标记,允许安装的依赖项具有灵活性,但代价是确定性构建。 如果您的项目的一个依赖项也使用模糊版本控制,当在传递依赖项中引入不兼容项时,这尤其危险。 请为所有依赖项使用固定版本,并尽可能使用 npm shrinkwrap 将它们锁定。

命名约定

命名项目很棘手,因为每个项目必须避免名称保留冲突,同时清晰地传达其目的和意图。 名称应考虑以下因素

  • 它如何将自身与 OpenStack 项目区分开来,作为 JavaScript 项目而不是 Python 项目。

  • 它如何将自身与 npm 或 bower 包区分开来,表明它是一个 OpenStack 项目。

  • 它如何清晰地传达它与哪个团队相关联?

  • 它如何传达其目的和内容?

  • 它如何适应 Gerrit 中的现有命名约定?

  • 它如何传达对同伴库的要求,例如 angular.js?

建议的名称模式
openstack/oslo-jslib

一个 JavaScript 库,包含其他 OpenStack 项目中使用的通用实用程序,发布到 bower 作为 openstack-oslo-jslib

openstack/ironic-jslib

一个与 Ironic API 集成的 JavaScript 库,发布到 bower 作为 openstack-ironic-jslib

openstack/ironic-jsclient

一个用 JavaScript 编写的 ironic 命令行客户端,发布到 npm 作为 openstack-ironic-jsclient

openstack/ironic-webclient

一个 Web 客户端,为 Ironic API 提供人类界面。

当工具规定现有的命名约定时,可能会出现异常。

eslint-config-openstack

ESLint 的 JavaScript 样式规则列表。

发布多个工件

如果您的 JavaScript 项目可以被多种类型的应用程序使用,则发布每个预期用途的单独工件通常很有帮助。

示例工件名称可能包括

  • openstack-oslo-jslib.ng.js

  • openstack-oslo-jslib.react.js