Verdaccio 插件

🌙
手机阅读
本文目录结构

插件介绍

Verdaccio 是插件应用程序。它可以通过多种方式扩展,包括新的身份验证方法,添加端点或使用自定义存储。

插件有 5 种类型:

  • 认证方式
  • 中间件
  • 存储
  • 自定义主题
  • 过滤器

使用

安装

$> npm install --global verdaccio-activedirectory

verdaccio 作为 sinopia 分支,它具有与兼容的插件的向后兼容性 sinopia@1.4.0。在这种情况下,安装是相同的。

$> npm install --global sinopia-memory

配置

打开 config.yaml 文件并按如下说明更新 auth 部分:

默认配置如下所示,由于在默认情况下我们使用一个内置的 htpasswd 插件,我们可以通过注释下面几行代码来禁用它:

认证配置

 htpasswd:
    file: ./htpasswd
    # max_users: 1000

如果你决定使用 ldap 插件,将上述部分进行替换。

auth:
  activedirectory:
    url: "ldap://10.0.100.1"
    baseDN: 'dc=sample,dc=local'
    domainSuffix: 'sample.local'

多个身份验证插件

从技术上讲这是可能的,这使得插件的顺序很重要,因为凭据将按顺序解析。

auth:
  htpasswd:
    file: ./htpasswd
    #max_users: 1000
  activedirectory:
    url: "ldap://10.0.100.1"
    baseDN: 'dc=sample,dc=local'
    domainSuffix: 'sample.local'

中间件配置

这是一个如何设置中间件插件的示例。所有中间件插件都必须在中间件名称空间中定义。

middlewares:
  audit:
    enabled: true

您可以跟着 audit middle plugin(审核中间插件)的基本范例。

https://github.com/verdaccio/verdaccio-audit

存储配置

这是一个如何设置存储插件的示例。所有存储插件都必须在商店名称空间中定义。

store:
  memory:
    limit: 1000

主题配置

Verdaccio 允许将用户界面替换为自定义界面,我们将其称为 theme。默认情况下,

使用 @verdaccio/ui-theme 内置,但您可以使用其他方式安装自己的插件。

$> npm install --global verdaccio-theme-dark

插件名称前缀必须以开头 verdaccio-theme,否则插件将无法加载。

您一次只能加载一个主题,并在需要时通过选项。

theme:
  dark:
    option1: foo
    option2: bar

旧式插件

Sinopia 插件

如果您依赖任何 sinopia 插件,请记住它们已被弃用,将来可能无法正常工作。

  • sinopia-npm:支持 npm 注册表的 sinopia 认证插件。
  • sinopia-memory:在内存中缓存用户的 sinopia 认证插件。
  • sinopia-github-oauth-cli。
  • sinopia-crowd:支持 atlassian crowd 的 sinopia 认证插件。
  • sinopia-activedirectory:sinopia Active Directory 认证插件。
  • sinopia-github-oauth:sinopia2 的认证插件,支持 github oauth web flow。
  • sinopia-delegated-auth:将认证代理给另一个 HTTP URL 的 Sinopia 认证插件。
  • sinopia-altldap:另一个 Sinopia LDAP 认证插件
  • sinopia-request:一个简单易用且功能齐全的认证插件,可以通过配置使用外部 API。
  • sinopia-htaccess-gpg-email:使用 htaccess 格式生成密码,通过 GPG 加密并通过 MailGun API 发送给用户。
  • sinopia-mongodb:一个易用且功能齐全的认证插件,可通过配置使用 mongodb 数据库。
  • sinopia-htpasswd:支持 htpasswd 格式的 sinopia 认证插件。
  • sinopia-leveldb:针对 Sinopia private npm 的基于 leveldb 的 Sinopia 认证插件。
  • sinopia-gitlabheres:sinopia Gitlab 认证插件。
  • sinopia-gitlab:sinopia Gitlab 认证插件。
  • sinopia-ldap:sinopia LDAP 认证插件。
  • sinopia-github-oauth-env:基于 github oauth web flow 的 Sinopia 认证插件。

所有 sinopia 插件都应该和所有 verdaccio 将来版本兼容。

开发插件

我们建议使用我们的 Typescript 类型定义来开发插件。

主题插件

插件必须返回一个返回字符串的函数。

该字符串应该是用户界面根目录的绝对位置。

API

const path = require('path');

module.exports = (...arguments) => {
  return path.join(__dirname, 'static');
};

插件名称必须以 verdaccio-theme-prefix 开头很重要。

主题例子

@verdaccio/ui-theme:基于 React.js 的默认 Verdaccio 主题。

过滤器插件

根据要求引入了过滤器插件,以便能够从上行链路中过滤元数据。

PR 中的更多信息。

filters:
   storage-filter-blackwhitelist:
     filter_file: /path/to/file

API

该方法 filter_metadata 将允许您过滤来自任何上行链路的元数据,该方法 Promise 基于并必须返回修改后的相同元数据。

不要从元数据中删除属性,请尝试不要变异而是返回一个新对象。

interface IPluginStorageFilter<T> extends IPlugin<T> {
    filter_metadata(packageInfo: Package): Promise<Package>;
}

开发人员指南

帮助你开发插件

插件生成器

安装 Yeoman Generator

Verdaccio 是一个可插入的应用程序,其目的是帮助开发人员生成新的插件,

我们在 Yeoman 有一个自定义生成器,用于生成各种插件。

要安装生成器,首先必须安装 yeoman 命令 yo。

npm install -g yo

然后,在终端中安装运行以下命令的定制生成器。

npm i -g generator-verdaccio-plugin

使用发电机

使用 yeoman 非常简单,您可以在此处阅读有关它的更多信息。

成功安装后,请 yo verdaccio-plugin 在您的终端中运行并按照以下步骤操作。

➜ yo verdaccio-plugin

Just found a `.yo-rc.json` in a parent directory.
Setting the project root at: /Users/user/verdaccio_yo_generator

     _-----_     ╭──────────────────────────╮
    |       |    │        Welcome to        │
    |--(o)--|    │ generator-verdaccio-plug │
   `---------´   │   in plugin generator!   │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

? What is the name of your plugin? (customname)
1. 最佳实务*

我们建议使用 Typescript 开发新的插件,我们提供了对 Types 的广泛支持,可帮助您进行开发。

? What is the name of your plugin? my-plugin
? Select Language (Use arrow keys)
❯ typescript
  javascript

在描述您的插件时,要简短明了,请记住一个好的描述会增加您使用插件的机会。

? Please, describe your plugin (An amazing verdaccio plugin)

不要犹豫,包括有意义的关键字,如 verdaccio,plugin 或者你的插件类型。

好的关键字将帮助我们找到您,并在我们收集所有插件信息的过程中为您提供进一步的改进。

? Key your keywords (comma to split) verdaccio,plugin,storage,minio,verdaccio-plugin

不断更新您的生成器,不要错过任何错误修复和性能改进。

2. 贡献

帮助我们改进生成器,您可以在以下存储库中做出贡献。

身份验证插件

什么是身份验证插件?

是一种排序插件,允许处理谁访问或发布到特定程序包。默认情况下,它 htpasswd 是内置的,但可以轻松地由您自己替换。

入门

身份验证插件在本 auth: 节中定义,如下所示:

auth:
  htpasswd:
    file: ./htpasswd

也可以链接多个插件:

auth:
  htpasswd:
    file: ./htpasswd
  anotherAuth:
    foo: bar
    bar: foo
  lastPlugin:
    foo: bar
    bar: foo

如果链中的一个插件能够解决请求,则下一个插件将被忽略。

身份验证插件如何工作?

基本上我们必须用一个叫做 authenticate 的单一方法来返回一个 object(对象),此方法将接收到 3 个参数 (user, password, callback)。

在每次请求时,authenticate 都会触发,插件应返回凭据,如果 authenticate 失败,则 $anonymous 默认情况下将回退到角色。

API
interface IPluginAuth<T> extends IPlugin<T> {
    authenticate(user: string, password: string, cb: AuthCallback): void;
    adduser?(user: string, password: string, cb: AuthCallback): void;
    changePassword?(user: string, password: string, newPassword: string, cb: AuthCallback): void;
    allow_publish?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void;
    allow_access?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void;
    allow_unpublish?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void;
    apiJWTmiddleware?(helpers: any): Function;
}

只有 adduser,allow_access,apiJWTmiddleware,allow_publish 和 allow_unpublish 是可选的,verdaccio 在所有这些情况下,提供一个备用的。

apiJWTmiddleware 方法

apiJWTmiddleware 为了完全控制令牌处理程序而在 PR#1227 上引入,重写此方法将禁用 login/adduser 支持。

我们建议除非完全必要,否则不要实现此方法。在这里查看完整的示例。

https://github.com/verdaccio/verdaccio/pull/1227#issuecomment-463235068

我应该在每种方法中返回什么?

Verdaccio callback 在撰写本文时依赖于功能。

每个方法都应调用该方法,并且返回的内容很重要,让我们回顾一下如何做。

authentication 回调

一旦执行了认证,有两个选项来回应 verdaccio。

  • 如果认证失败

如果 auth 不成功,则 false 作为第二个参数返回。

callback(null, false)
  • 如果认证成功

授权成功

groups是用户组成的一组字符串。

callback(null, groups);
  • 如果认证产生错误

身份验证服务可能会失败,并且您可能希望在用户响应中反映出来,例如:服务不可用。

import { getInternalError } from '@verdaccio/commons-api';
callback(getInternalError('something bad message), null);

登录失败与服务错误不同,如果您想通知用户 credentails 错误,只需返回 false 一组字符串即可。行为主要取决于您。

adduser 回调
  • 如果 adduser 成功

如果服务能够创建用户,请 true 作为第二个参数返回。

callback(null, true)
  • 如果 adduser 失败

除成功以外的任何其他操作都必须返回错误。

import { getConflict } from '@verdaccio/commons-api';
const err = getConflict('maximum amount of users reached');
callback(err);
changePassword 回调
  • 如果请求成功

如果服务能够创建用户,请 true 作为第二个参数返回。

const user = serviceUpdatePassword(user, password, newPassword);

callback(null, user)
  • 如果请求失败

除成功以外的任何其他操作都必须返回错误。

import { getNotFound } from '@verdaccio/commons-api';
 const err = getNotFound('user not found');
callback(err);
allow_access,allow_publish 或 allow_unpublish 回调

这些方法旨在允许或拒绝触发某些动作。

  • 如果请求成功

如果服务能够创建用户,则返回 a true 作为第二个参数。

allow_access(user: RemoteUser, pkg: PackageAccess, cb: Callback): void {
  const isAllowed: boolean = checkAction(user, pkg);

  callback(null, isAllowed)
}
  • 如果请求失败

除成功以外的任何其他操作都必须返回错误。

import { getNotFound } from '@verdaccio/commons-api';
const err = getForbidden('not allowed to access package');
callback(err);

生成身份验证插件

有关详细信息,请查看我们的插件生成器。yo 在您的终端中运行命令,然后按照下列步骤操作。

➜ yo verdaccio-plugin

Just found a `.yo-rc.json` in a parent directory.
Setting the project root at: /Users/user/verdaccio_yo_generator

     _-----_     ╭──────────────────────────╮
    |       |    │        Welcome to        │
    |--(o)--|    │ generator-verdaccio-plug │
   `---------´   │   in plugin generator!   │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

? What is the name of your plugin? service-name
? Select Language typescript
? What kind of plugin you want to create? auth
? Please, describe your plugin awesome auth plugin
? GitHub username or organization myusername
? Author's Name Juan Picado
? Author's Email jotadeveloper@gmail.com
? Key your keywords (comma to split) verdaccio,plugin,auth,awesome,verdaccio-plugin
   create verdaccio-plugin-authservice-name/package.json
   create verdaccio-plugin-authservice-name/.gitignore
   create verdaccio-plugin-authservice-name/.npmignore
   create verdaccio-plugin-authservice-name/jest.config.js
   create verdaccio-plugin-authservice-name/.babelrc
   create verdaccio-plugin-authservice-name/.travis.yml
   create verdaccio-plugin-authservice-name/README.md
   create verdaccio-plugin-authservice-name/.eslintrc
   create verdaccio-plugin-authservice-name/.eslintignore
   create verdaccio-plugin-authservice-name/src/index.ts
   create verdaccio-plugin-authservice-name/index.ts
   create verdaccio-plugin-authservice-name/tsconfig.json
   create verdaccio-plugin-authservice-name/types/index.ts
   create verdaccio-plugin-authservice-name/.editorconfig

I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.


⸨ ░░░░░░░░░░░░░░░░░⸩ ⠋ fetchMetadata: sill pacote range manifest for @babel/plugin-syntax-jsx@^7.7.4 fetc

安装完成后,访问您的项目目录。

➜ cd verdaccio-plugin-service-name
➜ cat package.json

  {
  "name": "verdaccio-plugin-service-name",
  "version": "0.0.1",
  "description": "awesome auth plugin",
  ...

完整实施 ES5 示例

function Auth(config, stuff) {
  var self = Object.create(Auth.prototype);
  self._users = {};

  // config for this module
  self._config = config;

  // verdaccio logger
  self._logger = stuff.logger;

  // pass verdaccio logger to ldapauth
  self._config.client_options.log = stuff.logger;

  return self;
}

Auth.prototype.authenticate = function (user, password, callback) {
  var LdapClient = new LdapAuth(self._config.client_options);
  ....
  LdapClient.authenticate(user, password, function (err, ldapUser) {
    ...
    var groups;
     ...
    callback(null, groups);
  });
};

module.exports = Auth;

配置将如下所示:

auth:
  htpasswd:
    file: ./htpasswd

htpasswd 插件名称的后缀在哪里。例如:verdaccio-htpasswd 主体的其余部分将是插件配置参数。

列出社区身份验证插件
  • verdaccio-bitbucket:verdaccio Bitbucket 认证插件。
  • verdaccio-bitbucket-server:verdaccio 的 Bitbucket 服务器身份验证插件。
  • verdaccio-ldap:verdaccio 的 LDAP 身份验证插件。
  • verdaccio-active-directory:verdaccio 的 Active Directory 身份验证插件
  • verdaccio-gitlab:使用 GitLab 个人访问令牌进行身份验证
  • verdaccio-gitlab-ci:启用 GitLab CI 来针对 verdaccio 进行身份验证。
  • verdaccio-htpasswd:基于 htpasswd 文件插件(内置)的 verdaccio 身份验证
  • verdaccio-github-oauth:verdaccio 的 Github oauth 认证插件。
  • verdaccio-github-oauth-ui:verdaccio 登录按钮的 GitHub OAuth 插件。
  • verdaccio-groupnames:用于使用 $group 语法处理动态组关联的插件。与 ldap 插件配合使用效果最佳。

中间件插件

什么是中间件插件?

中间件插件具有修改 API(Web 和 cli)层的能力,可以添加新的端点或拦截请求。

API
interface IPluginMiddleware<T> extends IPlugin<T> {
  register_middlewares(app: any, auth: IBasicAuth<T>, storage: IStorageManager<T>): void;
}
register_middlewares

该方法通过 auth 和提供了对身份验证和存储的完全访问权限 storage

app 是允许您添加新端点的快速应用程序。

public register_middlewares(
    app: Application,
    auth: IBasicAuth<CustomConfig>,
    storage: IStorageManager<CustomConfig>
  ): void {
    const router = Router();
    router.post(
      '/custom-endpoint',
      (req: Request, res: Response & { report_error?: Function }, next: NextFunction): void => {
        const encryptedString = auth.aesEncrypt(Buffer.from(this.foo, 'utf8'));
        res.setHeader('X-Verdaccio-Token-Plugin', encryptedString.toString());
        next();
      }
    );
    app.use('/-/npm/something-new', router);
  }

authstorage 这样的例子,可以延长,但我们不建议这种方法,除非有充分的理由。

verdaccio-audit 是中间件插件的一个很好的例子。

https://github.com/verdaccio/monorepo/tree/master/plugins/audi

生成中间件插件

有关详细信息,请查看我们的插件生成器。

yo 在您的终端中运行命令,然后按照下列步骤操作。

➜ yo verdaccio-plugin

Just found a `.yo-rc.json` in a parent directory.
Setting the project root at: /Users/user/verdaccio_yo_generator

     _-----_     ╭──────────────────────────╮
    |       |    │        Welcome to        │
    |--(o)--|    │ generator-verdaccio-plug │
   `---------´   │   in plugin generator!   │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

? What is the name of your plugin? custom-endpoint
? Select Language typescript
? What kind of plugin you want to create? middleware
? Please, describe your plugin awesome middleware plugin
? GitHub username or organization myusername
? Author's Name Juan Picado
? Author's Email jotadeveloper@gmail.com
? Key your keywords (comma to split) verdaccio,plugin,middleware,awesome,verdaccio-plugin
   create verdaccio-plugin-custom-endpoint/package.json
   create verdaccio-plugin-custom-endpoint/.gitignore
   create verdaccio-plugin-custom-endpoint/.npmignore
   create verdaccio-plugin-custom-endpoint/jest.config.js
   create verdaccio-plugin-custom-endpoint/.babelrc
   create verdaccio-plugin-custom-endpoint/.travis.yml
   create verdaccio-plugin-custom-endpoint/README.md
   create verdaccio-plugin-custom-endpoint/.eslintrc
   create verdaccio-plugin-custom-endpoint/.eslintignore
   create verdaccio-plugin-custom-endpoint/src/index.ts
   create verdaccio-plugin-custom-endpoint/index.ts
   create verdaccio-plugin-custom-endpoint/tsconfig.json
   create verdaccio-plugin-custom-endpoint/types/index.ts
   create verdaccio-plugin-custom-endpoint/.editorconfig

I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.


⸨ ░░░░░░░░░░░░░░░░░⸩ ⠋ fetchMetadata: sill pacote range manifest for @babel/plugin-syntax-jsx@^7.7.4 fetc

安装完成后,访问您的项目目录。

➜ cd verdaccio-plugin-auth-service-name
➜ cat package.json

  {
  "name": "verdaccio-plugin-custom-endpoint",
  "version": "0.0.1",
  "description": "awesome middleware plugin",
  ...

中间件是在内置端点之后注册的,因此无法覆盖已实现的中间件。

列出社区中间件插件
  • verdaccio-audit:用于 npm audit cli 支持的 verdaccio 插件(内置)(从 3.x 开始兼容)
  • verdaccio 型材式 API:verdacci 插件 NPM 轮廓 CLI 支持和 NPM 轮廓设置的密码为 verdaccio-htpasswd 的基于 authentificaton
  • verdaccio-https 如果设置了 x-forward-proto 标头,则 Verdaccio 中间件插件可重定向到 https

存储插件

什么是存储插件?

默认情况下,Verdaccio 使用文件系统存储插件 local-storage。可以使用社区插件或自己创建一个插件来轻松替换默认存储。

API

存储插件由两个对象,IPluginStorage和组成 IPackageStorage。

  • 该 IPluginStorage 对象处理私有软件包的本地数据库。
  interface IPluginStorage<T> extends IPlugin<T>, ITokenActions {
    logger: Logger;
    config: T & Config;
    add(name: string, callback: Callback): void;
    remove(name: string, callback: Callback): void;
    get(callback: Callback): void;
    getSecret(): Promise<string>;
    setSecret(secret: string): Promise<any>;
    getPackageStorage(packageInfo: string): IPackageStorage;
    search(onPackage: onSearchPackage, onEnd: onEndSearchPackage, validateName: onValidatePackage): void;
  }
  • IPackageStorage 是由每个请求创建一个对象,该手柄用于元数据和压缩档的 I / O 操作。
interface IPackageStorage {
  logger: Logger;
  writeTarball(pkgName: string): IUploadTarball;
  readTarball(pkgName: string): IReadTarball;
  readPackage(fileName: string, callback: ReadPackageCallback): void;
  createPackage(pkgName: string, value: Package, cb: CallbackAction): void;
  deletePackage(fileName: string, callback: CallbackAction): void;
  removePackage(callback: CallbackAction): void;
  updatePackage(
    pkgFileName: string,
    updateHandler: StorageUpdateCallback,
    onWrite: StorageWriteCallback,
    transformPackage: PackageTransformer,
    onEnd: CallbackAction
  ): void;
  savePackage(fileName: string, json: Package, callback: CallbackAction): void;
}

生成中间件插件

有关详细信息,请查看我们的插件生成器。

yo 在您的终端中运行命令,然后按照下列步骤操作。

➜ yo verdaccio-plugin

Just found a `.yo-rc.json` in a parent directory.
Setting the project root at: /Users/user/verdaccio_yo_generator

     _-----_     ╭──────────────────────────╮
    |       |    │        Welcome to        │
    |--(o)--|    │ generator-verdaccio-plug │
   `---------´   │   in plugin generator!   │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

? What is the name of your plugin? custom-endpoint
? Select Language typescript
? What kind of plugin you want to create? storage
? Please, describe your plugin awesome storage plugin
? GitHub username or organization myusername
? Author's Name Juan Picado
? Author's Email jotadeveloper@gmail.com
? Key your keywords (comma to split) verdaccio,plugin,storage,awesome,verdaccio-plugin
   create verdaccio-plugin-storage-package-database/package.json
   create verdaccio-plugin-storage-package-database/.gitignore
   create verdaccio-plugin-storage-package-database/.npmignore
   create verdaccio-plugin-storage-package-database/jest.config.js
   create verdaccio-plugin-storage-package-database/.babelrc
   create verdaccio-plugin-storage-package-database/.travis.yml
   create verdaccio-plugin-storage-package-database/README.md
   create verdaccio-plugin-storage-package-database/.eslintrc
   create verdaccio-plugin-storage-package-database/.eslintignore
   create verdaccio-plugin-storage-package-database/src/PackageStorage.ts
   create verdaccio-plugin-storage-package-database/src/index.ts
   create verdaccio-plugin-storage-package-database/src/plugin.ts
   create verdaccio-plugin-storage-package-database/index.ts
   create verdaccio-plugin-storage-package-database/tsconfig.json
   create verdaccio-plugin-storage-package-database/types/index.ts
   create verdaccio-plugin-storage-package-database/.editorconfig

I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.


⸨ ░░░░░░░░░░░░░░░░░⸩ ⠋ fetchMetadata: sill pacote range manifest for @babel/plugin-syntax-jsx@^7.7.4 fetc
列出社区存储插件

以下插件列表实现存储 API,可以被用作示例。

  • verdaccio-memory 在内存中装载包的存储插件
  • verdaccio-s3-storage 存储插件以托管程序包 Amazon S3
  • verdaccio-aws-s3-storage 存储插件,用于托管 Amazon S3 程序包(由 Verdaccio 核心团队维护)
  • verdaccio-google-cloud Storage 插件,用于托管软件包 Google Cloud Storage
  • verdaccio-minio 一个 verdaccio 插件,用于在 Minio 中存储数据

节点 API

Verdaccio 可以通过程序调用。 在版本 verdaccio@3.0.0 之后引入了节点 API。

使用

编程

import startServer from 'verdaccio';

startServer(configJsonFormat, 6000, store, '1.0.0', 'verdaccio',
(webServer, addrs, pkgName, pkgVersion) => {
    webServer.listen(addr.port || addr.path, addr.host, () => {
        console.log('verdaccio running');
    });
});

其他执行

  • verdaccio-server 本地 npm registry proxy server(代理服务器)
// js
import * as verdaccioServer from "verdaccio-server";
verdaccioServer.start();
verdaccioServer.stop();
verdaccioServer.list();
verdaccioServer.stopAll();
verdaccioServer.show();
verdaccioServer.cli();
// windows .net2
verdaccioServer.serviceInstall();
verdaccioServer.serviceUninstall();
verdaccioServer.serviceStart();
verdaccioServer.serviceStop();
verdaccioServer.serviceRestart();

AXIHE / 精选资源

浏览全部教程

面试题

学习网站

前端培训
自己甄别

前端书籍

关于朱安邦

我叫 朱安邦,阿西河的站长,在杭州。

以前是一名平面设计师,后来开始接接触前端开发,主要研究前端技术中的JS方向。

业余时间我喜欢分享和交流自己的技术,欢迎大家关注我的 Bilibili

关注我: Github / 知乎

于2021年离开前端领域,目前重心放在研究区块链上面了

我叫朱安邦,阿西河的站长

目前在杭州从事区块链周边的开发工作,机械专业,以前从事平面设计工作。

2014年底脱产在老家自学6个月的前端技术,自学期间几乎从未出过家门,最终找到了满意的前端工作。更多>

于2021年离开前端领域,目前从事区块链方面工作了