博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
力荐!这些工具可以帮你写出干净的代码
阅读量:7049 次
发布时间:2019-06-28

本文共 14747 字,大约阅读时间需要 49 分钟。

想写出好代码,却不知道从哪里开始?想删除死代码?想在代码库中找出未被使用的变量?想在代码中找出有问题的模式?

你是多元化团队的负责人吗?你的团队中有新来的开发人员吗?你担心他们会写出不符合标准的代码吗?在代码评审时是否花了一整天的时间去检查代码标准,而不是实际的逻辑实现?

我一直在做这样的事情,经常忙得像热锅上的蚂蚁。但从现在开始,我们要保证永远不再担心这类问题。在阅读本文过程中,如果遇到困难,可以参考代码库()。

本文更多地是针对React应用程序,但同样适用于其他Web项目。

让我们从Prettier开始吧

什么是Prettier?

Prettier是一种代码格式化程序,它以特定的方式为你格式化代码。

请看这个GIF:

\"\"

我们为什么需要Prettier?

  • 清理现有代码库:通过单个命令行清理代码库。想象一下清理超过20,000行代码的代码库会是怎样的一种情景。

  • 易于适用:Prettier在格式化代码时使用争议最少的编码风格。因为是开源的,很多人已经在修复一些边缘情况和优化体验方面进行了多次迭代。

  • 编写代码:人们没有意识到的是,他们花了很多时间用于格式化代码,这浪费了他们太多的精神能量。让Prettier来处理格式化的事情,开发人员就可以专注在核心业务逻辑上。Prettier可以将效率提高10%。

  • 帮助新手:如果你是一位与优秀工程师并肩工作的新手,并且你希望自己看起来很酷,可以写出干净的代码,那就使用Prettier吧。

如何设置Prettier?

创建一个叫作app的文件夹,进入该文件夹,在命令行中敲入:

npm init -y

这将在app文件夹中创建一个package.json文件。

我将在本文中使用yarn,但你也可以使用npm。

安装我们的第一个依赖项:

yarn add --dev prettier

这将安装package.json中指定的开发依赖项,如下所示:

{  \u0026quot;name\u0026quot;: \u0026quot;react-boiler-plate\u0026quot;,  \u0026quot;version\u0026quot;: \u0026quot;1.0.0\u0026quot;,  \u0026quot;description\u0026quot;: \u0026quot;A react boiler plate\u0026quot;,  \u0026quot;main\u0026quot;: \u0026quot;src/index.js\u0026quot;,  \u0026quot;author\u0026quot;: \u0026quot;Adeel Imran\u0026quot;,  \u0026quot;license\u0026quot;: \u0026quot;MIT\u0026quot;,  \u0026quot;scripts\u0026quot;: {    \u0026quot;prettier\u0026quot;: \u0026quot;prettier --write src/**/*.js\u0026quot;  },  \u0026quot;devDependencies\u0026quot;: {    \u0026quot;prettier\u0026quot;: \u0026quot;^1.14.3\u0026quot;  }}

稍后我会解释“prettier”: “prettier — write src/**/*.js”的作用,现在先让我们在app文件夹中创建一个src/文件夹。在src/文件夹中,再创建一个名为index.js的文件——名字可以随意起。

在index.js文件中,按原样粘贴这句话:

let person =                     {  name: \u0026quot;Yoda\u0026quot;,                designation: 'Jedi Master '                };              function trainJedi (jediWarrion) {if (jediWarrion.name === 'Yoda') {  console.log('No need! already trained');}console.log(`Training ${jediWarrion.name} complete`)              }trainJedi(person)              trainJedi({ name: 'Adeel',              designation: 'padawan'   });

到目前为止,我们有了一个src/app/index.js文件,包含了一些难看的代码。

我们可以做三件事:

  • 手动缩进并格式化代码;
  • 使用自动化工具;
  • 保持不变(请不要这么做)。

我打算选择第二项,所以我们安装了一个依赖项,并在package.json中声明了Prettier。

现在在app根文件夹中创建一个prettier.config.js文件,并在其中添加一些Prettier规则:

module.exports = {  printWidth: 100,  singleQuote: true,  trailingComma: 'all',  bracketSpacing: true,  jsxBracketSameLine: false,  tabWidth: 2,  semi: true,};

printWidth将确保你的单行代码不会超过100个字符。

singleQuote会将所有双引号转换为单引号。

trailingComma将确保在最后一个对象属性的末尾会有一个逗号。

bracketSpacing在对象字面量之间打印空格:

If bracketSpacing is true - Example: { foo: bar }If bracketSpacing is false - Example: {foo: bar}

jsxBracketSameLine将在多行JSX元素的最后一行放置\u0026gt;:

// true example\u0026lt;button  className=\u0026quot;prettier-class\u0026quot;  id=\u0026quot;prettier-id\u0026quot;  onClick={this.handleClick}\u0026gt;  Click Here\u0026lt;/button\u0026gt;// false example\u0026lt;button  className=\u0026quot;prettier-class\u0026quot;  id=\u0026quot;prettier-id\u0026quot;  onClick={this.handleClick}\u0026gt;  Click Here\u0026lt;/button\u0026gt;

tabWidth指定单个缩进的空格数。

如果semi设置为true,将在语句末尾加上;。

现在让我们来说说这个脚本的作用:

“prettier”: “prettier  — write src/**/*.js”

它的意思是运行prettier,并让它在src/文件夹中查找所有的.js文件。–write标志告诉prettier要把格式化好的内容保存到文件中,并找出格式化过程中发现的任何异常。

现在在终端中运行这个脚本:

yarn prettier

这是我在运行代码时看到的:

\"\"

ESLint

什么是代码linter?

代码linting是一种代码静态分析,通常被用于查找不符合某些样式指南的有问题的模式或代码。大多数编程语言都有代码linting,编译器有时会在编译过程中加入linting。

——来自ESLint

为什么JavaScript需要linter?

由于JavaScript是动态类型的,而且是一种松散类型的语言,因此开发人员在使用这门语言时很容易犯错。因为不经过编译,所以通常需要在执行.js文件的情况下才能发现语法或其他错误。

像ESLint这样的linting工具可以帮助开发人员在不执行JavaScript代码的情况下发现问题。

是什么让ESLint如此特别?

ESLint中的所有东西都是可插拔的,你甚至可以在运行时添加规则。你添加的每个linting规则都是独立的,任何一个规则都可以独自打开或关闭。每个规则都可以设置为警告或错误级别。

现在有2个流行的风格指南:

  • Google JavaScript Style Guide();

  • Airbnb JavaScript Style Guide()。

我一直在使用Airbnb的风格指南。这个风格指南一直有人在维护,在本文中,我将使用受Airbnb风格指南启发的规则集。

首先更新package.json文件:

{  \u0026quot;name\u0026quot;: \u0026quot;react-boiler-plate\u0026quot;,  \u0026quot;version\u0026quot;: \u0026quot;1.0.0\u0026quot;,  \u0026quot;description\u0026quot;: \u0026quot;A react boiler plate\u0026quot;,  \u0026quot;main\u0026quot;: \u0026quot;src/index.js\u0026quot;,  \u0026quot;author\u0026quot;: \u0026quot;Adeel Imran\u0026quot;,  \u0026quot;license\u0026quot;: \u0026quot;MIT\u0026quot;,  \u0026quot;scripts\u0026quot;: {    \u0026quot;lint\u0026quot;: \u0026quot;eslint --debug src/\u0026quot;,    \u0026quot;lint:write\u0026quot;: \u0026quot;eslint --debug src/ --fix\u0026quot;,    \u0026quot;prettier\u0026quot;: \u0026quot;prettier --write src/**/*.js\u0026quot;  },  \u0026quot;husky\u0026quot;: {    \u0026quot;hooks\u0026quot;: {      \u0026quot;pre-commit\u0026quot;: \u0026quot;lint-staged\u0026quot;    }  },  \u0026quot;lint-staged\u0026quot;: {    \u0026quot;*.(js|jsx)\u0026quot;: [\u0026quot;npm run lint:write\u0026quot;, \u0026quot;git add\u0026quot;]  },  \u0026quot;devDependencies\u0026quot;: {    \u0026quot;babel-eslint\u0026quot;: \u0026quot;^8.2.3\u0026quot;,    \u0026quot;eslint\u0026quot;: \u0026quot;^4.19.1\u0026quot;,    \u0026quot;eslint-config-airbnb\u0026quot;: \u0026quot;^17.0.0\u0026quot;,    \u0026quot;eslint-config-jest-enzyme\u0026quot;: \u0026quot;^6.0.2\u0026quot;,    \u0026quot;eslint-plugin-babel\u0026quot;: \u0026quot;^5.1.0\u0026quot;,    \u0026quot;eslint-plugin-import\u0026quot;: \u0026quot;^2.12.0\u0026quot;,    \u0026quot;eslint-plugin-jest\u0026quot;: \u0026quot;^21.18.0\u0026quot;,    \u0026quot;eslint-plugin-jsx-a11y\u0026quot;: \u0026quot;^6.0.3\u0026quot;,    \u0026quot;eslint-plugin-prettier\u0026quot;: \u0026quot;^2.6.0\u0026quot;,    \u0026quot;eslint-plugin-react\u0026quot;: \u0026quot;^7.9.1\u0026quot;,    \u0026quot;husky\u0026quot;: \u0026quot;^1.1.2\u0026quot;,    \u0026quot;lint-staged\u0026quot;: \u0026quot;^7.3.0\u0026quot;,    \u0026quot;prettier\u0026quot;: \u0026quot;^1.14.3\u0026quot;  }}

在开始进行配置之前,先让我们来看看每个依赖包的功能。

babel-eslint:这个包让你可以轻松在Babel上使用lint。如果你不使用ESLint尚不支持的Flow或实验性功能,则不一定需要这个插件。

eslint:这是lint代码所需的主要工具。

eslint-config-airbnb:这个包提供了所有Airbnb的ESLint配置,你可以修改它们。

eslint-plugin-babel:babel-eslint的插件伴侣。

eslint-plugin-import:这个插件旨在支持ES2015+(ES6+)的导入/导出语法,并防止出现拼写错误的文件路径和导入名称。

eslint-plugin-jsx-a11y:适用于JSX元素可访问性规则的linting规则。

eslint-plugin-prettier:让ESLint与Prettier的使用更顺畅。

eslint-plugin-react:特定于React的linting规则。

eslint-config-jest-enzyme:用于特定于React和Enzyme的全局变量。这个lint配置让ESLint知道有哪些全局变量,并且不会针对它们发出警告——有点像断言it和describe。

eslint-plugin-jest:Jest的ESLint插件。

husky:在自动化部分会进行更多介绍。

lint-staged:在自动化部分会进行更多介绍。

现在我们已经有了基本的了解,接下来可以开始了。

在app/根目录创建.eslintrc.js文件:

module.exports = {\tenv: {\t\tes6: true,\t\tbrowser: true,\t\tnode: true,\t},\textends: ['airbnb', 'plugin:jest/recommended', 'jest-enzyme'],\tplugins: [\t\t'babel',\t\t'import',\t\t'jsx-a11y',\t\t'react',\t\t'prettier',\t],\tparser: 'babel-eslint',\tparserOptions: {\t\tecmaVersion: 6,\t\tsourceType: 'module',\t\tecmaFeatures: {\t\t\tjsx: true\t\t}\t},\trules: {\t\t'linebreak-style': 'off', // Don't play nicely with Windows.\t\t'arrow-parens': 'off', // Incompatible with prettier\t\t'object-curly-newline': 'off', // Incompatible with prettier\t\t'no-mixed-operators': 'off', // Incompatible with prettier\t\t'arrow-body-style': 'off', // Not our taste?\t\t'function-paren-newline': 'off', // Incompatible with prettier\t\t'no-plusplus': 'off',\t\t'space-before-function-paren': 0, // Incompatible with prettier\t\t'max-len': ['error', 100, 2, { ignoreUrls: true, }], // airbnb is allowing some edge cases\t\t'no-console': 'error', // airbnb is using warn\t\t'no-alert': 'error', // airbnb is using warn\t\t'no-param-reassign': 'off', // Not our taste?\t\t\u0026quot;radix\u0026quot;: \u0026quot;off\u0026quot;, // parseInt, parseFloat radix turned off. Not my taste.\t\t'react/require-default-props': 'off', // airbnb use error\t\t'react/forbid-prop-types': 'off', // airbnb use error\t\t'react/jsx-filename-extension': ['error', { extensions: ['.js'] }], // airbnb is using .jsx\t\t'prefer-destructuring': 'off',\t\t'react/no-find-dom-node': 'off', // I don't know\t\t'react/no-did-mount-set-state': 'off',\t\t'react/no-unused-prop-types': 'off', // Is still buggy\t\t'react/jsx-one-expression-per-line': 'off',\t\t\u0026quot;jsx-a11y/anchor-is-valid\u0026quot;: [\u0026quot;error\u0026quot;, { \u0026quot;components\u0026quot;: [\u0026quot;Link\u0026quot;], \u0026quot;specialLink\u0026quot;: [\u0026quot;to\u0026quot;] }],\t\t\u0026quot;jsx-a11y/label-has-for\u0026quot;: [2, {\t\t\t\u0026quot;required\u0026quot;: {\t\t\t\t\u0026quot;every\u0026quot;: [\u0026quot;id\u0026quot;]\t\t\t}\t\t}], // for nested label htmlFor error\t\t'prettier/prettier': ['error'],\t},};

还要在app/根目录中添加.eslintignore文件:

/.git/.vscodenode_modules

我们先介绍一下.eslintrc.js文件的作用。

先把它拆分一下:

module.exports = {    env:{},    extends: {},    plugin: {},    parser: {},    parserOptions: {},    rules: {},};
  • env:用于预定义全局变量。在我们的例子中,可用的环境包括es6、browser和es6。es6将启用除模块之外的所有ECMAScript 6功能。browser将添加所有浏览器全局变量,如Windows。node将添加Node全局变量和Node作用域,比如global。

  • extends:字符串数组——扩展了之面配置的额外配置选项。现在我们正在使用airbnb的linting规则,这些规则被扩展到jest,然后是jest-enzyme。

  • plugins:插件基本上就是我们想要使用的linting规则。现在我们正在使用babel、import、jsx-a11y、react、prettier。

  • parser:默认情况下,ESLint使用Espree,但因为我们使用了babel,我们还需要使用Babel-ESLint。

  • parserOptions:如果我们将Espree的默认解析器更改为babel-eslint,需要指定parserOptions——它是必需的。我通过选项告诉ESLint,ecmaVersion是6。因为我们在EcmaScript模块(而不是script)中编写代码,所以我们将sourceType指定为module。由于我们使用了React,引入了JSX,所以在ecmaFeatures中加了jsx选项,并将其设置为true。

  • rules:我们已经扩展并通过插件添加的所有规则,我们可以更改或覆盖它们。

现在介绍一下.eslintignore。

.eslintignore里包含了我们不希望ESLint对它们进行lint的路径列表。这里我只指定三个:

  • /.git——我不希望Git相关文件被lint。
  • /.vscode——由于我使用的是VS Code,这个编辑器提供了自己的配置文件,我不希望配置文件被lint。
  • node_modules——我不希望依赖项被lint,所以把这个目录也添加到列表中。

接下来让我们来看看package.json中新添加的脚本。

\u0026quot;lint\u0026quot;: \u0026quot;eslint --debug src/\u0026quot;\u0026quot;lint:write\u0026quot;: \u0026quot;eslint --debug src/ --fix\u0026quot;
  • $ yarn lint——运行这个命令,它将遍历src/中的所有文件,并在每个找到错误的文件中提供详细日志,你可以手动打开这些文件并更正错误。

\"\"

  • $ yarn lint:write——运行这个命令,它将执行与上述命令相同的操作。不同的地方在于,如果它可以纠正它发现的错误,它将纠正它们,并尝试从代码中尽可能多地移除代码坏气味。

让它更自动化一些

到目前为止,我们设置好了prettier和eslint,但每次我们都要运行脚本。接下来我们让它更加自动化一些。

  • 在编辑器中按下ctrl + s时格式化和lint代码。
  • 每次提交代码时,自动对代码进行lint和格式化。

要在保存代码时进行格式化和lint,需要使用像VS Code这样的编辑器:

安装ESLint扩展插件。在此()下载插件或在VS Code编辑器中按下ctrl + shift + x打开扩展模块,搜索eslint,将出现一系列插件。安装Dirk Ba​​eumer开发的那个。安装完成后,点击reload按钮重新启动编辑器。

安装好这个插件后,在app/根文件夹中创建一个名为.vscode/的文件夹 ——不要忘了那个点号,这个非常重要。

在文件夹中创建一个settings.json文件,如下所示:

{  \u0026quot;editor.formatOnSave\u0026quot;: false,  \u0026quot;eslint.autoFixOnSave\u0026quot;: true,}
  • editor.formatOnSave——我在这里将它设置为false,因为我不希望文件格式的默认编辑器配置与ESLint和Prettier发生冲突。

  • eslint.autoFixOnSave——我在这里将它设置为true,因为我希望每次在保存文件时安装的插件都能正常工作。由于ESLint的配置关联了Prettier的配置,所以每次在点击保存时,它都会格式化和lint你的代码。

需要注意的是,当你运行yarn lint:write时,它也会lint和美化你的代码。

试想一下,如果你有2万行代码,然后通过手动的方式进行审计和改进,然后再想象一下用一个命令就可以完成所有事情。手动方法可能需要30天,而自动方法可能只需要30秒。

脚本已经设置好了,每次点击保存时,编辑器都会对特定文件做出神奇的回应。但是,并不是团队中的每个人都会选择使用VS Code。不过没关系,我们可以更自动化一些。

husky

什么是husky?

husky()是一个Git钩子,你可以在提交代码前或在将代码推送到分支时执行某些特定的操作。

你所要做的就是安装husky:

yarn add --dev husky

然后在package.json文件中添加以下内容:

\u0026quot;husky\u0026quot;: {       \u0026quot;hooks\u0026quot;: {           \u0026quot;pre-commit\u0026quot;: \u0026quot;YOUR_COMMAND_HERE\u0026quot;,      \u0026quot;pre-push\u0026quot;: \u0026quot;YOUR_COMMAND_HERE\u0026quot;      }  },

每次在提交或推送代码时,它都会执行某个脚本或命令——比如运行测试用例或格式化代码。

lint-staged

什么是lint-staged?

lint-staged()可以在暂存(Git staged)文件上运行linter,这样就不会将错误的代码推送到分支上。

为什么要用lint-staged?

在提交代码之前进行lint是很有意义的,你可以确保没有错误进入到代码库中,并且可以强制应用代码样式。但在整个项目上运行lint过程会很慢,而且有些lint结果可能无关紧要。你可能只想对要提交的文件进行lint。

这个项目提供了一个脚本,这个脚本将执行任意的shell任务,并将暂存文件列表作为参数,按指定的通配模式进行文件过滤。

你要做的是安装lint-staged:

yarn add --dev lint-staged

然后在package.json文件中添加:

\u0026quot;lint-staged\u0026quot;: {       \u0026quot;*.(js|jsx)\u0026quot;: [\u0026quot;npm run lint:write\u0026quot;, \u0026quot;git add\u0026quot;]  },

这段配置的意思是先运行lint:write命令,然后将文件添加到暂存区域。它仅针对.js和.jsx文件运行这个命令,但你也可以根据需要针对其他文件运行这个命令。

husky与lint-staged一起使用

每次提交代码之前,都会运行一个叫作lint-staged的脚本,这个脚本将运行npm run lint:write命令,这个将lint并格式化你的代码,然后将代码添加到暂存区并提交。

最终的package.json文件应如下所示。

{  \u0026quot;name\u0026quot;: \u0026quot;react-boiler-plate\u0026quot;,  \u0026quot;version\u0026quot;: \u0026quot;1.0.0\u0026quot;,  \u0026quot;description\u0026quot;: \u0026quot;A react boiler plate\u0026quot;,  \u0026quot;main\u0026quot;: \u0026quot;src/index.js\u0026quot;,  \u0026quot;author\u0026quot;: \u0026quot;Adeel Imran\u0026quot;,  \u0026quot;license\u0026quot;: \u0026quot;MIT\u0026quot;,  \u0026quot;scripts\u0026quot;: {    \u0026quot;lint\u0026quot;: \u0026quot;eslint --debug src/\u0026quot;,    \u0026quot;lint:write\u0026quot;: \u0026quot;eslint --debug src/ --fix\u0026quot;,    \u0026quot;prettier\u0026quot;: \u0026quot;prettier --write src/**/*.js\u0026quot;  },  \u0026quot;husky\u0026quot;: {    \u0026quot;hooks\u0026quot;: {      \u0026quot;pre-commit\u0026quot;: \u0026quot;lint-staged\u0026quot;    }  },  \u0026quot;lint-staged\u0026quot;: {    \u0026quot;*.(js|jsx)\u0026quot;: [\u0026quot;npm run lint:write\u0026quot;, \u0026quot;git add\u0026quot;]  },  \u0026quot;devDependencies\u0026quot;: {    \u0026quot;babel-eslint\u0026quot;: \u0026quot;^8.2.3\u0026quot;,    \u0026quot;eslint\u0026quot;: \u0026quot;^4.19.1\u0026quot;,    \u0026quot;eslint-config-airbnb\u0026quot;: \u0026quot;^17.0.0\u0026quot;,    \u0026quot;eslint-config-jest-enzyme\u0026quot;: \u0026quot;^6.0.2\u0026quot;,    \u0026quot;eslint-plugin-babel\u0026quot;: \u0026quot;^5.1.0\u0026quot;,    \u0026quot;eslint-plugin-import\u0026quot;: \u0026quot;^2.12.0\u0026quot;,    \u0026quot;eslint-plugin-jest\u0026quot;: \u0026quot;^21.18.0\u0026quot;,    \u0026quot;eslint-plugin-jsx-a11y\u0026quot;: \u0026quot;^6.0.3\u0026quot;,    \u0026quot;eslint-plugin-prettier\u0026quot;: \u0026quot;^2.6.0\u0026quot;,    \u0026quot;eslint-plugin-react\u0026quot;: \u0026quot;^7.9.1\u0026quot;,    \u0026quot;husky\u0026quot;: \u0026quot;^1.1.2\u0026quot;,    \u0026quot;lint-staged\u0026quot;: \u0026quot;^7.3.0\u0026quot;,    \u0026quot;prettier\u0026quot;: \u0026quot;^1.14.3\u0026quot;  }}

现在,每当你提交代码时:

$ git add .$ git commit -m \u0026quot;some descriptive message here\u0026quot;

它将根据.eslintrc.js文件的所有规则对代码进行lint和格式化。有了这个,你就可以确保没有坏代码被推到生产环境中。

现在介绍一下EditorConfig

首先在app/根文件夹中创建一个.editorconfig文件,然后在该文件中粘贴以下代码:

# EditorConfig is awesome: http://EditorConfig.org# top-most EditorConfig fileroot = true[*.md]trim_trailing_whitespace = false[*.js]trim_trailing_whitespace = true# Unix-style newlines with a newline ending every file[*]indent_style = spaceindent_size = 2end_of_line = lfcharset = utf-8insert_final_newline = truemax_line_length = 100

那么EditorConfig是什么东西?

并不是每个人都会使用VS Code,所以为了让每个人保持统一(例如在制表符空格或换行方面),我们使用.editorconfig,这样有助于强制执行某些规则。

支持EditorConfig()的编辑器包括Web Storm、App Code、Atom、Eclipse、Emacs、bbedit,等等。

上述的配置将执行以下操作:

  • 去掉.md和.js文件中的尾部空格;
  • 将缩进样式设置为空格而不是制表符;
  • 缩进大小为2;
  • 行尾是lf,这样每个人不管使用的是哪种操作系统,都会有相同的行尾;
  • 文件末尾应该有一个新行;
  • 单行的最大度应为100个字符。

英文原文:

更多内容,可关注前端之巅(ID:frontshow)

\"\"

转载地址:http://jskol.baihongyu.com/

你可能感兴趣的文章
《敏捷时代》作者访谈录
查看>>
Scrum Guides 2017年最新修改
查看>>
Cling旨在提供一款高性能的C++ REPL
查看>>
关于《在Windows与.NET平台上的持续交付实践》的问答录
查看>>
TensorFlow模型的签名推荐与快速上线\n
查看>>
改变的六条规则
查看>>
GitHub是如何改进自身的DNS架构的
查看>>
IntelliJ IDEA 2018.3 新版本发布,支持 Java 12及Spring Boot增强等特性
查看>>
阿里重磅发布大规模图神经网络平台AliGraph,架构算法解读
查看>>
AWS Amplify Console:赋予应用程序快速部署的能力
查看>>
Git漏洞导致攻击者可在用户电脑上运行任意代码
查看>>
书评 —— 《Go语言编程》
查看>>
红帽收购混合云管理提供商NooBaa,混合云爆发节点临近!
查看>>
保持分布式团队同步
查看>>
QCon上海2015盛大开幕
查看>>
Jakarta EE:云原生Java的新平台
查看>>
2018 Node.js用户调查报告显示社区仍然在快速成长
查看>>
WhiteSource推出免费开源的漏洞检查工具
查看>>
聊天机器人已死,为什么腾讯还要打造自己的智能客服?
查看>>
如何打造一流的查询引擎,构建优秀的数据仓库?
查看>>