Пришло время создать библиотеку компонентов пользовательского интерфейса для вашей команды.

внешний интерфейс
Пришло время создать библиотеку компонентов пользовательского интерфейса для вашей команды.

1. Стек технологий

Давайте кратко рассмотрим технологические стеки, задействованные в создании библиотеки компонентов пользовательского интерфейса команды:

  • Создайте приложение React: официально поддерживаемый скаффолдинг CLI, обеспечивающий современную настройку сборки без настройки;
  • React: библиотека JavaScript для создания пользовательских интерфейсов;
  • Ant Design: набор языков дизайна пользовательского интерфейса корпоративного уровня и библиотеки компонентов React;
  • Сборник рассказов: инструмент, помогающий в разработке элементов управления пользовательского интерфейса, создание независимых элементов управления с помощью истории, чтобы каждая разработка элемента управления имела независимую среду разработки и отладки;
  • TypeScript: самый популярный интерфейсный язык 2020 года, надмножество типов JavaScript;
  • ESLint && husky: унифицировать стиль командного кода;
  • Jest: среда тестирования JavaScript для модульного тестирования библиотек компонентов;
  • Travis CI: предоставляет услуги непрерывной интеграции для непрерывной интеграции и непрерывного развертывания проектов;

2. Подготовка проекта

2.1 Создание инженерной среды для библиотек компонентов

использоватьCreate React AppСоздайте интерфейсную инженерную среду для библиотек компонентов пользовательского интерфейса.

npx create-react-app ii-admin-base --typescript

2.2 Установить сборник рассказов

Для автоматической установки Storybook используйте следующую команду:

npx -p @storybook/cli sb init --type react_scripts

  • параметрreact_scriptsИспользуется, чтобы сообщить Storybook текущий элемент для использованияCreate React AppСозданный Storybook автоматически установит соответствующий пакет на основе этого параметра.

2.3 Установите плагин Storybook

2.3.1 addon-infoплагин

addon-infoПлагин автоматически распознает реквизиты, переданные компонентом, для создания формы.

yarn add @storybook/addon-info -D yarn add @types/storybook__addon-info -D

3. Настройте сборник рассказов

Прежде чем настраивать Storybook, давайте кратко разберемся с процессом загрузки историй.

Идет загрузка историй.storybook/main.jsили.storybook/preview.jsв этих двух файлах. Самый простой способ загрузить истории — по имени файла. Предположим, что ваш файл историй находится вsrc/componentsкаталог, вы можете загрузить его следующим образом:

// .storybook/main.js

module.exports = {
  stories: ['../src/components/**/*.stories.js'],
};

или можно найти на.storybook/preview.jsзагрузить всеstories:

import { configure } from '@storybook/react';

configure(require.context('../src/components', true, /\.stories\.js$/), module);

Примечание: в.storybook/preview.jsфайл, может быть вызван только один разconfigureфункция.

configureФункция принимает параметры как:

  • одинарный require.context "req"
  • Массив «req» для загрузки файлов из нескольких мест;
  • Возвращаемое значениеvoidилиan array of module exportsфункция загрузки;

Если вы хотите загрузить из нескольких мест, вы можете использовать метод массива следующим образом:

import { configure } from '@storybook/react';

configure(
  [
    require.context('../src/components', true, /\.stories\.js$/),
    require.context('../lib', true, /\.stories\.js$/),
  ],
  module
);

Примечание:

Если вы хотите импортировать все файлы в папке или импортировать все файлы, соответствующие регулярному выражению, вы можете использовать функциюrequire.context().require.context()Функция имеет 3 параметра:

  • Каталог папок для поиска;
  • следует ли также искать его подкаталоги;
  • и регулярное выражение, соответствующее файлу;

3.1 Истории порядка отображения конфигурации

Как изменить порядок отображения историй? Пример следующий:welcome.stories.tsxСначала добавьте в массив, чтобы изменить порядок отображения историй:

import { configure } from '@storybook/react';

// 将 welcome 文档说明置于顶部
const loaderFn = () => {
  const allExports = [require('../src/welcome.stories.tsx')];
  const req = require.context('../src/components', true, /\.stories\.tsx$/);
  req.keys().forEach((fname) => allExports.push(req(fname)));

  return allExports;
};

// automatically import all files ending in *.stories.tsx
configure(loaderFn, module);

3.2 Поддержка машинописного текста

Базовая библиотека компонентов, которую нужно построить, написана на основе Typescript, поэтому необходимо добавить поддержку Typescript. настроить./storybook/main.jsфайл со следующим содержимым:

  webpackFinal: async (config) => {
    config.module.rules.push({
      test: /\.(ts|tsx)$/,
      use: [
        {
          loader: require.resolve('babel-loader'),
          options: {
            presets: [require.resolve('babel-preset-react-app')],
          },
        },
      ],
    });

    return config;
  }

3.3 Настройка меньше

Базовая библиотека компонентов, которую необходимо построить, представляет собой вторичный пакет, основанный на Ant Design, поэтому он должен поддерживать меньшее количество компонентов. Для меньшего, настроить./storybook/main.jsфайл со следующим содержимым:

 // .storybook/main.js

 webpackFinal: async (config) => {
    config.module.rules.push({
      test: /\.(ts|tsx)$/,
      use: [
        {
          loader: require.resolve('babel-loader'),
          options: {
            presets: [require.resolve('babel-preset-react-app')],
          },
        },
      ],
    });

    config.module.rules.push({
      test: /\.less$/,
      loaders: [
        'style-loader',
        'css-loader',
        {
          loader: 'less-loader',
          options: {
            lessOptions: {
              javascriptEnabled: true,
            },
          },
        },
      ],
      include: [path.resolve(__dirname, '../src'), /[\\/]node_modules[\\/].*antd/],
    });

    return config;
  },

Завершите приведенную выше конфигурацию содержимого и найдите импортированный файл less.не удалось. В связи с этим вопросом были проведены следующие исследования.

Вопрос 1:
еслиless-loaderЕсли версия выше 6.0, следующая конфигурация будетсообщить об ошибке:

{
  loader: "less-loader",
  options: {
    javascriptEnabled: true
  }
}

Необходимо изменить на:

 {
   loader: 'less-loader',
     options: {
       lessOptions: {
         javascriptEnabled: true,
       },
     },
 }

Вопрос 2:
Между сборником рассказов 5.3.0 и сборником рассказов 5.2.x есть некоторые различия, см.Ссылка на ссылку. Загрузчик файлов cra(create-react-app) перехватит все остальные файлы, так что меньше файлов не сможет войти в less-loader. В ответ на эту проблему необходимо настроить @storybook/preset-create-react-app.Содержимое конфигурации выглядит следующим образом:

{
  name: '@storybook/preset-create-react-app',
    options: {
      craOverrides: {
        fileLoaderExcludes: ['less'],
      },
  },
}

Вопрос 3:
Базовая библиотека компонентов, созданная на этот раз, представляет собой вторичную инкапсуляцию, основанную на Ant Design.При обращении к компоненту Ant Design обнаруживается, что стиль не действует. Для решения этой проблемы вы можетеpreview.tsxНастройте следующим образом:

import { configure } from '@storybook/react';
import 'antd/dist/antd.less'    // 引入 antd 样式

3.4 Добавить глобальный декоратор

Запустите сборник рассказов, и вы обнаружите, что содержание рассказов справа находится рядом с панелью меню слева, и в целом ощущение очень компактное и неприглядное. Эту ситуацию обычно можно решить, добавив отступы. Так как же заставить отступы работать для всех историй в Storybook? В это время вам нужно использовать глобальный декоратор.

企业微信20200620091122.png
существует.storybookкаталоге создайте глобальный декоратор следующим образом:

// .storybook/decorators/WrapperDecorator/index.tsx

import React from 'react';

const wrapperStyle: React.CSSProperties = {
  padding: '20px 40px',
};

// 创建一个样式包裹的装饰器
const WrapperDecorator = (storyFn) => <div style={wrapperStyle}>{storyFn()}</div>;

export default WrapperDecorator;

Затем добавьте декоратор в файл preview.tsx.

// .storybook/preview.tsx 

import { addDecorator, configure } from '@storybook/react';
import WrapperDecorator from './decorators/WrapperDecorator';

import 'antd/dist/antd.less';

// 通过addDecorator添加插件
addDecorator(WrapperDecorator);

Окончательный эффект показан ниже.

WX20200620-092009.png

4. Разработка компонентов

4.1 Компонент ввода проверочного кода

Компонент ввода кода подтверждения в этом основном примере представляет собой компонент ввода с функцией отправки кода подтверждения, как показано на следующем рисунке.

Kapture 2020-06-27 at 9.55.02.gif
Весь компонент является вторичной разработкой компонента ввода Ant Design.Подробный код показан на следующем рисунке:

import React, { useState, FC } from 'react';
import { Input } from 'antd';
import { InputProps } from 'antd/lib/input';
import classNames from 'classnames';

export interface InputVerifyProps extends InputProps {
  /** 发送验证码接口函数 */
  sendCode: () => void;
  /** 倒计时时间 */
  countDown?: number;
  /** 初始验证码文本内容 */
  initCodeText?: string;
  /** 重新发送验证码文本内容 */
  reCodeText?: string;
  /** 验证码类名 */
  codeClassname?: string;
}

export const InputVerify: FC<InputVerifyProps> = (props) => {
  const { sendCode, countDown, initCodeText, reCodeText, codeClassname, ...restProps } = props;

  const [codeText, setCodeText] = useState(initCodeText);
  const [codeStatus, setCodeStatus] = useState(false);
  
  const handleCountDown = (timer: ReturnType<typeof setTimeout> | null, count: number) => {
    if (timer) {
      clearTimeout(timer);
    }

    if (count <= 0) {
      setCodeText(reCodeText);
      setCodeStatus(false);
    } else {
      setCodeText(`${count} s`);

      const newTimer: ReturnType<typeof setTimeout> = setTimeout(() => {
        handleCountDown(newTimer, count - 1);
      }, 1000);
    }
  };

  const handleCodeClick = () => {
    if (codeStatus) return;

    sendCode && sendCode();
    setCodeStatus(true);
    handleCountDown(null, countDown as number);
  };

  const codeCls = classNames('ii-verify-button', codeClassname, {
    'ii-verify-button-disabled': codeStatus,
  });

  return (
    <Input
      data-testid="test-input-verify"
      {...restProps}
      suffix={
        <span className={codeCls} onClick={handleCodeClick}>
          {codeText}
        </span>
      }
    />
  );
};

InputVerify.defaultProps = {
  countDown: 60,
  initCodeText: '发送验证码',
  reCodeText: '重新发送',
};

export default InputVerify;

4.2 Добавление модульных тестов

После выполнения задач по разработке компонентов следующим шагом будет добавление модульных тестов. Для компонента ввода проверочного кода модульный тест в основном делится на два аспекта: с одной стороны, он проверяет, нормально ли работает компонент antd native Input, а с другой стороны, он проверяет, нормально ли работает компонент ввода проверочного кода.

import React from 'react';
import { render, fireEvent, wait, RenderResult } from '@testing-library/react';
import '@testing-library/jest-dom';
import '@testing-library/jest-dom/extend-expect';
import InputVerify, { InputVerifyProps } from './InputVerify';

const antdProps: InputVerifyProps = {
  placeholder: 'antd input placeholder',
  size: 'large',
  sendCode: jest.fn(),
  onPressEnter: jest.fn(),
  onChange: jest.fn(),
};

const selfProps: InputVerifyProps = {
  countDown: 3,
  initCodeText: '发送验证码',
  reCodeText: '再次发送',
  sendCode: jest.fn(),
};

let wrapper: RenderResult, inputElement: HTMLInputElement;

describe("Test InputVerify component on the props of antd's input component", () => {
  beforeEach(() => {
    wrapper = render(<InputVerify {...antdProps} />);
    inputElement = wrapper.getByTestId('test-input-verify') as HTMLInputElement;
  });

  it("should have the input's class of antd", () => {
    expect(inputElement).toBeInTheDocument();
    expect(inputElement).toHaveClass('ant-input');
  });

  it('should support size', () => {
    expect(inputElement).toHaveClass('ant-input-lg');
  });

  it('should trigger onChange event correctly', () => {
    fireEvent.change(inputElement, { target: { value: 'input test' } });
    expect(antdProps.onChange).toHaveBeenCalled();
    expect(inputElement.value).toEqual('input test');
  });
});

describe("Test InputVerify component on the self's props", () => {
  beforeEach(() => {
    wrapper = render(<InputVerify {...selfProps} />);
  });

  it('should render the correct InputVerify component', () => {
    const suffixElement = wrapper.getByText('发送验证码');

    expect(suffixElement).toBeInTheDocument();
    expect(suffixElement).toHaveClass('ii-verify-button');
  });

  it('click verify button should call the right callback ', async () => {
    const suffixElement = wrapper.getByText('发送验证码');

    fireEvent.click(suffixElement);
    expect(selfProps.sendCode).toHaveBeenCalled();

    await wait(
      () => {
        expect(wrapper.getByText('再次发送')).toBeInTheDocument();
      },
      { timeout: 4000 }
    );
  });
});

4.3 Документация по компонентам

При разработке отдельного компонента также необходимо добавить соответствующую документацию, чтобы рассказать другим, как использовать этот компонент.

4.3.1 Автоматически создавать документацию

Если вы хотите автоматически генерировать документацию компонента с помощью аннотаций, вам нужно использоватьreact-docgenплагин. из-за@storybook/addon-infoЗависимая пара пакетовreact-docgenПлагин интегрирован, поэтому при написании комментариев просто следуйтеJSDocСтандарт для написания соответствующей документации будет создан.

/**
 * 带验证码功能的输入组件,适用于要发送验证码的场景。
 *
 * ## 引用方法
 *
 * ~~~javascript
 * import { InputVerfiy } from 'ii-admin-base'
 * ~~~
 */
export const InputVerify: FC<InputVerifyProps> = (props) => {

Уведомление: react-docgenПлагин требует, чтобы компоненты также передавалиexportспособ экспорта.

4.3.2 Фильтрация типов объектов

@storybook/addon-infoКогда подключаемый модуль автоматически создает документ с описанием типов реквизитов, он также автоматически генерирует реквизиты, унаследованные компонентом, которые не только включают реквизиты, содержащиеся в стороннем пакете зависимостей, но также могут включать собственные реквизиты HTML. элемент. Чтобы отфильтровать эти реквизиты, вам нужно полагаться на пакетreact-docgen-typescript-loader.

Сначала установите эту зависимость:

yarn add react-docgen-typescript-loader -D

затем настройтеmain.jsфайл, содержание конфигурации выглядит следующим образом:

// .storybook/main.js

config.module.rules.push({
  test: /\.(ts|tsx)$/,
  use: [
    {
      loader: require.resolve('babel-loader'),
      options: {
        presets: [require.resolve('babel-preset-react-app')],
      },
    },
    // 过滤 node_modules 中的 props
    {
      loader: require.resolve('react-docgen-typescript-loader'),
      options: {
        // 将枚举或者联合类型转换成字符串形式,避免字符串字面量显示别名。
        shouldExtractLiteralValuesFromEnum: true,
        // 避免显示原生内置属性
        propFilter: (prop) => {
          if (prop.parent) {
            return !prop.parent.fileName.includes('node_modules');
          }

          return true;
        },
      },
    },
  ],
});

Уведомление:

При использовании последней версии Storybook v5.3.19 обнаружено, что указанная выше конфигурация не действует. В ответ на эту проблему версию сборника рассказов можно уменьшить до 5.3.18, чтобы обойти ее.

WX20200620-165852.png

5. Соберите и протестируйте

5.1 Упаковка и сборка

5.1.1 Создание библиотеки компонентов модуля ввода файлов

существуетsrc/index.tsxВсе компоненты в файле импортируются, а затем экспортируются. Это позволяет импортировать все компоненты непосредственно из входного файла.

export { default as InputVerfiy } from './components/InputVerify';

5.1.2 Компиляция файлов TS

Использование CRA (Create-React-App) создаст приложение по умолчаниюtsconfig.jsonфайл, файл конфигурации связан со средой разработки. Для упаковки и компиляции библиотеки компонентов и генерации стандартных модулей ES необходимо создать отдельныйtsconfig.build.jsonдокумент.

/**
 * 用于最后打包编译
 */
{
  "compilerOptions": {
    // 文件输出目录
    "outDir": "dist",
    // ESNext: 是标准的ES Modules形式
    "module": "esnext",
    // 指定编译以后符合什么样的ES标准
    "target": "es5",
    // 为每一个js文件生成一个对应的.d.ts类型文件,方便使用组件库的用户可以获得类型检查和ts提示
    "declaration": true,
    // jsx 是一种语法糖,是React.createElement的缩写。此处置为react,编译出来的文件就可以用React.createElement来代替JSX语法的过程
    "jsx": "react",
    // tsc 处理模块的方式和node不一样,默认处理方式是"classic",针对绝对路径有的时候会找不到文件(一直向上找文件),所以需设置成'node'。
    "moduleResolution": "node",
    // 默认不支持 import React from 'react',只支持 import * as React from 'react'
    "allowSyntheticDefaultImports": true
  },
  // 要编译哪些文件
  "include": ["src"],
  "exclude": ["src/**/*.test.tsx", "src/**/*.stories.tsx"]
}

затем вpackage.jsonфайл добавленbuild:tsСкрипт для компиляции файлов TS в файлы модулей ES.

"build:ts": "tsc -p tsconfig.build.json",

5.1.3 Компиляция меньшего количества файлов

существуетpackage.jsonфайл добавленbuild:cssСкрипт для компиляции меньшего количества файлов в css.

"build:css": "lessc ./src/styles/index.less ./dist/index.css"

5.1.4 Настройка окончательного скрипта сборки

Настройте окончательный скрипт сборки в package.jsonbuild,Следующим образом:

 "clean": "rimraf ./dist",
 "build:ts": "tsc -p tsconfig.build.json",
 "build:css": "lessc ./src/styles/index.less ./dist/index.css",
 "build": "npm run clean && npm run build:ts && npm run build:css",
  • использоватьrimrafПолное удаление кроссплатформенных файлов;

5.2 Библиотека локальных тестовых компонентов

5.2.1 Добавить файл записи

Перед тестированием локальной библиотеки компонентов необходимо добавить входной файл библиотеки компонентов. настроитьpackage.jsonфайла, добавьте следующие поля:

"main": "dist/index.js",
"module": "dist/index.js",
"types": "dist/index.d.ts",

в:

  • mainПоле: определеноnpmфайл записи пакета;
  • moduleПоле: определеноnpmВходной файл для спецификации модуля ES6 пакета;

Примечание:используется здесьmainполя иmoduleполе, что эквивалентно публикации двух версий спецификации модуля в одном пакете. Когда упаковщик встречает наш модуль:

  1. Если он уже поддерживает поле pkg.module, он будет предпочтительно использовать версию спецификации модуля ES6, которая включает механизм Tree Shaking;
  2. Если он еще не распознает поле pkg.module, он будет использовать версию, которую мы скомпилировали в соответствии со спецификацией CommonJS, и не будет мешать процессу упаковки.

5.2.2 Использованиеnpm linkПротестировать локальную библиотеку компонентов

В каталоге библиотеки компонентов запуститеnpm linkкоманда, то есть создать мягкую ссылку на глобальный файл node_modules.

/Users/xxx/.nvm/versions/node/v12.14.0/lib/node_modules/ii-admin-base -> /Users/xxx/Job/ii-admin-base

Вне проекта создайте тестовый каталогtest-ii-admin-base, затем запустите в этом каталогеnpm link ii-admin-baseкоманда, которая проверит библиотеку компонентов каталогаii-admin-baseСсылка на глобальную:

➜ test-ii-admin-база npm link ii-admin-base /Users/xxx/Job/test-ii-admin-base/node_modules/ii-admin-base -> /Users/xxx/.nvm/versions/node/v12.14.0/lib/node_modules/ii-admin-base -> /Users/xxx/Job/ii-admin-base

Затем измените тестовый каталогtest-ii-admin-baseВ файле package.json добавьте зависимости вручную:

 "dependencies": {
    ...,
    "ii-admin-base": "0.1.0"

Это позволяет ссылаться на библиотеку компонентов в тестовом каталоге.ii-admin-base.

import { InputVerfiy } from 'ii-admin-base'
import 'ii-admin-base/dist/index.css'
import 'antd/dist/antd.css'

Примечание:Если во время теста сообщается следующая ошибка:

企业微信20200626052311.png
Это связано с тем, что мы использовали версию React при разработке библиотеки компонентов, а другая версия React использовалась в тестовом каталоге.Если в проекте несколько версий React, будет сообщено об указанной выше ошибке. В этом случае просто запустите следующую команду в каталоге библиотеки компонентов:npm link ../test-ii-admin-base/node_modules/react, то есть свяжите реактивную версию библиотеки компонентов с каталогом тестовых компонентов, а затем повторно запустите проект.

6. Опубликовать в NPM

6.1 Вход в учетную запись NPM

Сначала переключитесь на официальный зеркальный источник.

npm config set registry registry.npmjs.org/

Проверьте, авторизована ли текущая учетная запись:

npm whoami

Если вы не вошли в систему, используйтеnpm adduserВойдите в свою учетную запись.

6.2 Публикация в NPM

6.2.1 Добавить информацию о описании

Перед публикацией NPM вам также нужно настроитьpackage.jsonфайл, добавьте некоторую необходимую описательную информацию:

{
  "name": "ii-admin-base",
  "version": "0.1.0",
  "private": false,
  "description": "A library of react components, which mainly stores components that can be reused by all business lines of AI-Indeeded Company.",
  "author": "ShiMu",
  "license": "MIT",
  "keywords": [
    "React",
    "Component"
  ],
  "homepage": "https://lagrangelabs.github.io/ii-admin-base",
  "repository": {
    "type": "git",
    "url": "https://github.com/LagrangeLabs/ii-admin-base.git"
  },
  "files": [
    "build"
  ],
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "storybook": "start-storybook -p 9009 -s public",
    "build-storybook": "build-storybook -s public",
    "prepublishOnly": "npm run build"
  },
  ...
}

в:

  • Будуprivateполе установлено наfalse, представляет собой незакрытый пакет;
  • Добавить кdescription,author,license,keywordsи другие смежные области;
  • Добавить кhomepageполе, то есть URL домашней страницы проекта;
  • Добавить кrepositoryполе, то есть URL адреса склада проекта;
  • Добавить кfilesполе, указывающее, какие файлы загружать в npm. Если ничего не написано, будет использоваться значение по умолчанию.gitignoreинформация внутри. Но будьте осторожны, несмотря ни на что.gitignoreКак настроить, некоторые файлы всегда будут публиковаться на пакете, к этим файлам относятсяpackage.json,README.md,LICENSEтак далее;
  • Добавить кprepublishOnlyФункция ловушки, запускаемая в этой функции ловушкиnpm run build, чтобы убедиться, что перед выпуском пакетов NPM используется последний скомпилированный код;

6.2.2 КонфигурацияpeerDependenciesполе

Построенная на этот раз библиотека компонентов является вторичной инкапсуляцией Ant Design на основе React. Чтобы уменьшить размер библиотеки компонентов, сторонние зависимости, такие как React и Ant Design, обычно не упаковываются, во-вторых, если они упаковываются, это может вызвать конфликты между различными версиями.

В этом случае пользователю может быть предложено установить следующие основные зависимости, если он хочет использовать текущую библиотеку компонентов, напримерreact,Ant DesignПодождите, на этот раз вам нужно использоватьpackage.jsonсерединаpeerDependenciesполе. когда используешьnpm installПри установке зависимостейpeerDependenciesОбъявленные зависимости не будут установлены автоматически, но сообщите пользователю, что необходимо установить следующие зависимости, выводя журнал предупреждений.

"peerDependencies": {
    "react": ">= 16.8.0",
    "react-dom": ">= 16.8.0",
    "antd": ">= 4.3.5"
 },
  • Версия реакции должна быть выше или равна версии 16.8.0, поскольку хуки React были представлены в версиях выше версии 16.8.0;

6.2.3 Проверка спецификации кода и проверка модульного теста

Для компонентной библиотеки качество кода очень важно. В целях предотвращения соответствия кода не соответствует спецификациям команды или кода, которые не удаляют тесты единиц, от преданного или опубликованного, некоторые функции крючков необходимо использовать для проверки того, проверяют ли разработчики, прошедшие чеки кода и проверки модуля.

6.2.3.1 Добавление проверки спецификации кода

существуетpackage.jsonфайл, добавьте скрипт lint дляsrcФайлы в каталоге проверяются eslint.

 "lint": "eslint --ext js,ts,tsx, src --max-warnings 5",
  • --max-warnings 5: Указывает, что максимально допустимое количество предупреждений-предупреждений равно 5;
6.2.3.2 Добавление проверок модульного теста

Когда проект создается с помощью CRA, он создается по умолчанию.testScript, но скрипт используется в среде разработки, после выполнения он не вернет результат выполнения (то есть не вернет, прошло выполнение или нет), а всегда будет находиться в режиме наблюдения. В этом случае вы можете установить переменную окруженияCI=trueдля возврата результатов тестового запуска.

 "test:nowatch": "cross-env CI=true npm run test"
  • В разных средах операционных систем способ установки переменных среды отличается. Следовательно, необходимо использоватьcross-envЗависимые пакеты завершают настройку переменных кросс-платформенной среды.
6.2.3.3 Проверка процесса перед фиксацией или публикацией

Для кода фиксации установитеhuskyЗависимости, проверки модульных тестов и проверки спецификации кода выполняются перед отправкой кода, как показано ниже. Сделайте то же самое перед публикацией пакета NPM.

"scripts": {
    ...,
    "prepublishOnly": "npm run test:nowatch && npm run lint && npm run build"
  },
  "husky": {
    "hooks": {
      "pre-commit": "npm run test:nowatch && npm run lint"
    }
  },

После завершения вышеуказанной конфигурации запустите командуnpm publishПакет NPM опубликован.

Семь, настроить среду непрерывной интеграции

Базовая библиотека компонентов, которая обычно извлекается из каждого бизнес-направления, будет поддерживаться членами команды каждого бизнес-направления.В настоящее время организация Github, предоставляемая Github, может использоваться для совместного обслуживания этой библиотеки компонентов.

В этом случае непрерывная интеграция с Travis CI не так проста. Я написал статью раньшеКак использовать Travis CI для непрерывной интеграции кода в Github Organization, вы можете обратиться к этой статье, чтобы завершить настройку среды непрерывной интеграции библиотеки базовых компонентов.

8. Непрерывный выпуск

Travis CI также может автоматически публиковать библиотеки компонентов в NPM со следующими настройками:

  1. Войдите в центр личных учетных записей npm и создайте новый токен (выберите «Чтение и публикация» для получения разрешений), чтобы Travis CI мог публиковать пакеты npm.

image.png

  1. В каталоге библиотеки компонентов запуститеtravis setup npm --forceкоманду, обратите внимание, что эта команда перезапишет предыдущуюtravis.ymlдокумент. На этом этапе вам будет предложено ввести ключ API NPM, как показано ниже, скопируйте и вставьте значение токена, только что созданное здесь.

NPM api key: ************************************

переписанныйtravis.ymlдокумент:

language: node_js
node_js:
  - stable
cache:
  directories:
    - node_modules

env:
  matrix:
    - CI=true

script:
  - npm run build-storybook

deploy:
  # 发布到 gh-pages 上
  - provider: script
    skip_cleanup: true
    script: bash scripts/deploy.sh
    on:
      branch: master
  # 发布到 npm 上
  - provider: npm
    skip_cleanup: true
    email: xxxx@qq.com
    api_key:
      secure: Lsb1/coESXgnDgcotaObyV7QKDVeZJWpAcduyZt/bxAqspN/EdOR2duraPpBHKzme7tOHT4ybIAQusJqSl36K/WX2WFXqhKHw+FoFOobK1aa/azQDkpwllgdxrlx0fCbLpxBPDdKxbJspXwphSgCi2rjY8F/PBdy4+g8IEh/FJQckuFHAEhpTuk+SZPJT5eAqhctxXSaNKB712x4vX9AJLHRT791nB388dsjKOz2NWGNJ14arxukvnb/Yt02hHWKpGQPgQQY9QjfENYnspFYBXYssKV2nhC+0EFoXNn6UK3C4gXo96hV2yqFbP0AhZdHiYxOJ/v1KN7xt+I3popw+puETFyno4TgepGqU/EvkB5r3DnB9CrYsOpeN4+wZtfVtwxMxxxJ8q/EbC7RH45b39056B0i7PnJViIHLWps3XxFQ/bi1CgWdiFyzNofwCYVV6uT0UNR0XZDqUzre10GBrvDogMNWPKMaTmJCWVA8c6AkB4XjfU/jY1xaWxbNuD+Z+p3uLSTKm+c2xrUJFl5KW4/ocyS8No/J+e/9uNkXYcTEdkwnBioWfT7OaBrIpzrkKL9RftkDzjkeUo8h9/XpXNHEUGMK6ZDO0n3zlQ8/qcMHJvS5dXbKmvwZ9GNnOS1EvR1X32MlTfcW0EzDgCXufyAK6UdUGm7jm+dfJJkD60g=
    on:
      branch: master
      repo: LagrangeLabs/ii-admin-base

Примечание:Когда Travis CI постоянно публикует библиотеку компонентов, если сообщается о следующих проблемах:

sh: 1: cross-env: not found
npm ERR! code ELIFECYCLE
npm ERR! syscall spawn
npm ERR! file sh

Для решения этой проблемы былpackage.jsonв файлеcross-envзаменить./node_mdoules/.bin/cross-envВот и все.

 "test:nowatch": "./node_modules/.bin/cross-env CI=true npm run test"

9. Резюме

На данный момент завершен весь процесс создания библиотеки компонентов команды.

разное: