Процесс настройки проекта react + typescript

React.js

предисловие

  • Если вы хотите использовать реакцию, для новичков предпочтительнее использовать леса, созданные facebook, create-реагировать-приложение (портал 👉китайская документация create-реагировать на приложение).
  • create-react-app инкапсулирует конфигурацию webpack, конфигурацию lint, конфигурацию babel и т. д. вreact-scripts, этот подход гарантирует, что при обновлении и переносе базовой версии зависимостей ее можно будет безболезненно перенести, не затрагивая бизнес-проекты.
  • create-реагировать-приложение поддерживает разработчиков для персонализации конфигурации проекта (путем сотрудничестваreact-app-rewiredиспользовать илиyarn ejectИзмените его после раскрытия соответствующей конфигурации).
  • Далее представлены некоторые специальные настройки, которые я обычно делаю в проекте перед разработкой бизнес-кода, что полезно для последующей разработки проекта.

Инициализировать проект

  • Прежде чем использовать строительные леса, необходимо использоватьnpmКоманда для установки лесов глобально:
npm install -g create-react-app
  • После завершения установки можно собрать проект через строительные леса:
create-react-app my-app
  • TypeScript — это типизированный надмножество JavaScript, который компилируется в обычный JavaScript. Запустите новый проект create-реагировать-приложение с помощью TypeScript, выполнив следующую команду:
create-react-app my-app --typescript
  • Специальное примечание: Конфигурации проекта, описанные ниже, являются конфигурациями для проектов react + typescript.

Установите последнюю версию приложения create-реагировать

  • При создании проекта со старым пакетом create-react-app консоль предложит следующее:
A template was not provided. This is likely because you're using an outdated version of create-react-app.
Please note that global installs of create-react-app are no longer supported.

решение:

  • использоватьnpm uninstall -g create-react-appудалить старую версию
  • использоватьwhich create-react-appКоманда для проверки успешности удаления

Если вам будет предложено, как и мне (/usr/local/bin/create-react-app), запуститеrm -rf /usr/local/bin/create-react-appчтобы удалить это.

  • Установите новую версию:npm install -g create-react-app

react-scripts

  • Этот раздел в основном представляет собой некоторое связанное содержание React-Scripts. Если вы заинтересованы только в конфигурации, вы можете пропустить этот раздел.

  • Как упоминалось ранее, приложение create-react-app оборачивает слой в веб-пакет.react-scripts, с одной стороны, это может заставить новичков, не привыкших к eslint, babel и webpack, сосредоточиться только на написании компонентов, с другой стороны, они могут постоянно обновлять и улучшать параметры по умолчанию, не затрагивая бизнес-код.

  • видимый,react-scriptsЕго функция состоит в том, чтобы скрыть многие детали вверх путем инкапсуляции некоторых базовых конфигураций, так что бизнес-разработчикам нужно сосредоточиться только на разработке бизнес-кода.

  • Перейдите в каталог проекта node_modules, вы можете увидеть create-react-app + typescript вreact-scriptsСтруктура каталогов следующая:

    react-scripts目录结构
    • Папка scripts, которая содержит сценарии сборки и проекты разработки сценариев, соответствующая конфигурация веб-пакета помещается в папку конфигурации внутри.
  • Есть три способа изменить эти конфигурации:

    (1) пройтиreact-app-rewiredПереопределите конфигурацию веб-пакета по умолчанию.

    (2) вилка соответствующаяreact-scriptspackage, поддерживайте этот пакет зависимостей самостоятельно.

    (3) Непосредственно извлеките всю конфигурацию и сохраните ее в бизнес-проекте. Недостатком этой операции является то, что она необратима, и после того, как файл конфигурации открыт, его нельзя скрыть.

  • Поскольку я технология все еще неглубокая, примите третий вариант.

  • Сначала перейдите в каталог проекта:

cd my-app
  • незащищенныйreact-scriptsМешок:
yarn eject

yarn run v1.17.3
$ react-scripts eject
NOTE: Create React App 2+ supports TypeScript, Sass, CSS Modules and more without ejecting: https://reactjs.org/blog/2018/10/01/create-react-app-v2.html

? Are you sure you want to eject? This action is permanent. (y/N)
# 输入 y 即可
  • Как правило, указанная выше команда используется для предоставления доступа к проекту после использования строительных лесов для сборки проекта.react-scriptsМешок. И если вы устанавливаете другие зависимости или сначала меняете другое содержимое проекта, используйтеyarn ejectКоманда выдаст ошибку:
This git repository has untracked files or uncommitted changes:

Remove untracked files, stash or commit any changes, and try again.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! XXX@0.1.0 eject: `react-scripts eject`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the XXX@0.1.0 eject script.
npm ERR! This is probably not a problem with npm. There is likely additional log
ging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Administrator\AppData\Roaming\npm-cache\_logs\2019-8-1T0
3_18_15_677Z-debug.log
  • Не паникуйте, решение состоит в последовательном выполнении следующих команд:
git add .
git commit -am "init"
yarn eject
  • После успешного извлечения конфигурации вы можете обнаружить, что изменения в каталоге проекта следующие:

    项目目录的变化
  • Если вам нужно настроить проект, вы обычно изменяете веб-пакет по умолчанию в каталоге config.

Выполняйте индивидуальные проекты

  • Далее будет представлено, как внедрить в проектless,Добавить кtslintа такжеstylelint, импортreact-routerУпаковкаfetchЗапрос, введениеreact-loadableи загружать по требованиюantd.

ввести меньше

  • Установитьlessа такжеless-loader:
yarn add less less-loader –dev
  • Изменить конфигурацию WebPack, то есть добавить новую в файл config/webpack.config.jslessПеременные конфигурации:
const lessRegex = /\.less$/;  // 新增less配置
const lessModuleRegex = /\.module\.less$/; // 新增less配置
  • В то же время добавьте правило правила в модуль в файле config/webpack.config.js:
    module: {
      strictExportPresence: true,
      rules: [
        /* 省略代码 */
        {
          oneOf: [
            /* 省略代码 */
            /* 下面是原有代码块 */
            {
              test: cssModuleRegex,
              use: getStyleLoaders({
                importLoaders: 1,
                sourceMap: isEnvProduction && shouldUseSourceMap,
                modules: true,
                getLocalIdent: getCSSModuleLocalIdent,
              }),
            },
            /* 上面是原有代码块 */
            /* 下面是添加代码块 */
            {
              test: lessRegex,
              exclude: lessModuleRegex,
              use: getStyleLoaders({
                importLoaders: 1,// 值是1
                sourceMap: isEnvProduction && shouldUseSourceMap
              },
                "less-loader"
              ),
              sideEffects: true
            },
            {
              test: lessModuleRegex,
              use: getStyleLoaders({
                importLoaders: 1,
                sourceMap: isEnvProduction && shouldUseSourceMap,
                modules: true, // 增加这个可以通过模块方式来访问less
                getLocalIdent: getCSSModuleLocalIdent
              },
                "less-loader"
              )
            },
            /* 上面是添加代码块 */
            /* 下面是原有代码块 */
            {
              test: sassRegex,
              exclude: sassModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 2,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                },
                'sass-loader'
              ),
              sideEffects: true,
            },
            /* 上面是原有代码块 */
          ],
        },
      ],
    },
import * as styles from ./index.module.less
  • Точка! Если вы хотите сделать модульное внедрение в проектless, так же нужно настроить в файле src/react-app-env.d.ts, иначе ts сообщит об ошибке Cannot find module './index.module.less', содержание конфигурации следующее:
declare module '*.less' {
  const styles: any;
  export = styles;
}
  • Вышеупомянутое сделаноlessПредставлен в проекте react + typescript.

Конфигурация редактора

  • При ежедневной разработке часто переключаются разные редакторы, и конфигурацию приходится устанавливать заново. Командная разработка, все используют разные редакторы и имеют разный стиль настройки. Добавив файл .editorconfig в корневой каталог проекта и настроив определенные правила, вы можете настроить разные редакторы для поддержки согласованных спецификаций кода.
  • Ниже моя конфигурация:
# http://editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[Makefile]
indent_style = tab

Добавьте tslint и stylelint в проект

  • tslint: Подобно eslint, он фактически ограничивает стиль нашего логического кода, который можно настроить, добавив файл .tslint.json в корневой каталог проекта. Как правило, можно прямо указать, например,"extends": ["tslint-react"], Если есть специальные правила, вы можете добавить их самостоятельно. Пример содержания:
{
  "extends": ["tslint-react"],
  "rules": {
    /* 自己添加的特殊规则 */
  }
}
  • Stylelint: стиль кода стиля, который может ограничивать наш стиль, можно настроить, добавив файл .stylelintrc в корневом каталоге проекта. Как правило, можно прямо указать, например,"extends": ["stylelint-config-standard"], Если есть специальные правила, вы можете добавить их самостоятельно. Пример содержания:
{
  "extends": "stylelint-config-standard",
  "rules": {
    /* 自己添加的特殊规则 */
  }
}
  • Вышеупомянутое завершено в проектеtslintа такжеstylelintдополнение.

Представьте реактивный маршрутизатор

  • Некоторые люди захотят сказать, нетyarn add react-routerВам все еще нужно учить? На самом деле нет, см. следующее:
  • React Router теперь разделен на три пакета:react-router,react-router-dom,react-router-native.
  • Не следует устанавливать непосредственно в процессе разработкиreact-router, этот пакет предоставляет основные компоненты и функции маршрутизации для приложений React Router, а два других пакета предоставляют компоненты, специфичные для среды (браузер иreact-nativeсоответствующей платформе), но они также будутreact-routerЭкспортированные модули экспортируются снова.
  • Мы должны выбрать эти два пакета, которые адаптируются к среде разработки.Поскольку мне нужно создать веб-сайт (работает в браузере), я установилreact-router-dom. При этом, так как я тоже использую в проекте машинописный текст, мне также необходимо установить@types/react-router-dom. Команда установки:
yarn add react-router-dom
yarn add @types/react-router-dom --dev
  • Вышеупомянутое завершено в проектеreact-routerвступление.

Инкапсулировать запрос на получение

  • Если только простой запрос, не нужно вводитьaixos, путем инкапсуляции соответствующего кода запроса на выборку в файле request.js/request.ts и введения соответствующего метода запроса при его использовании.Есть несколько преимуществ:

    • Там меньше кода, где делаются запросы.

    • Общие ошибки могут быть добавлены в одном месте.

    • Запросы на пользовательские ошибки или сами запросы также могут быть обработаны.

    • Хорошая масштабируемость, добавление функций нужно изменить только в одном месте.

  • Ниже приведено конкретное содержимое файла request.ts, которое я инкапсулировал в проекте:

// path:src/utils/request.ts
const request = (url: string, config: any) => {
  return fetch(url, config)
    .then((res: any) => {
      if (!res.ok) {
        // 服务器异常返回
        throw Error('接口请求异常');
      }
      return res.json();
    })
    .catch((error: any) => {
      return Promise.reject(error);
    });
};

// GET请求
export const get = (url: string) => {
  return request(url, { method: 'GET' });
};

// POST请求
export const post = (url: string, data: any) => {
  return request(url, {
    body: JSON.stringify(data),
    headers: {
      'content-type': 'application/json',
    },
    method: 'POST',
  });
};
  • Создавайте различные модули запросов на основе функций, например модули списка:
// path:src/services/api/list.ts

import * as Fetch from '../../utils/request';

export async function getListData () {
  return Fetch.get('URL1');
}

export async function getListItemDetail (id: number) {
  return Fetch.get(
    `URL2/${id}`,
  ); 
}
  • Выложите API:
// path:src/services/api.ts

export * from './api/list';
  • Используемые компоненты:
// path:src/components/xxx.tsx

import React from 'react';
import * as api from '../../services/api';

class HomePage extends React.Component<any> {
  /* 省略代码 */ 

  async loadListData () {
    try {
      const res = await api.getListData();
      this.setState({
        listData: res.data.list,
      });
    } catch (error) {
      // do something
    }
  }
  
  /* 省略代码 */ 
}

export default HomePage;

  • Вышеупомянутое успешно завершеноfetchИнкапсуляция запроса.

Внедрить реактивно-загружаемый

  • Существует растущая тенденция в приложениях, использующих одностраничные приложения React.js. Часть приложения (или пути) может импортировать большое количество компонентов, которые не нужны при первой загрузке. Это увеличивает начальное время загрузки нашего приложения.
  • когда мы используемyarn buildПри упаковке проекта create-react-app сгенерирует большой файл, содержащий весь JavaScript, необходимый нашему приложению. Однако, если пользователь просто загружает страницу входа для входа в систему, для нас не имеет смысла загружать остальную часть приложения вместе с ней.
  • Чтобы решить эту проблему, в create-react-app есть очень простой встроенный метод для разделения нашего кода, эта функция называется Code Splitting.
  • Настройки проекта поддерживают разделение кода с помощью динамического импорта(). Мы можем использовать стороннюю библиотеку под названием react-loadable, которая учитывает различные ситуации, такие как сбой загрузки компонента, загрузка и так далее.
  • Сначала установитеreact-loadable, при этом, так как я тоже использую машинописный текст в проекте, мне также необходимо установить@types/react-loadable. Команда установки:
yarn add react-loadable
yarn add @types/react-loadable --dev
  • Для того, чтобы вход выглядел более кратким документом, я разделю конфигурацию маршрутизации на файл route.tsx, просто на вход файла маршрутизации App.tsxrouteDataИмпортируйте и используйте:
// path:src/App.tsx

import { createHashHistory } from 'history';
import React from 'react';
import { Router } from 'react-router';
import routeData from './common/route';

const history = createHashHistory();

const App: React.FC = () => {
  return (
    <Router history={history}>
      <Switch>
        {routeData.map(({ path, component, exact }: IRouterItem) => (
          <Route key={path} path={path} component={component} exact={exact} />
        ))}
        <Route component={NotFound} />
      </Switch>
    </Router>
  );
};

export default App;

  • Содержимое файла route.tsx примерно следующее:
// path:src/common/route.tsx

import * as React from 'react';
import Loadable from 'react-loadable';
import Loading from '../components/Loading';

const routeConfig: any = [
  {
    path: '/',
    component: asyncLoad(() => import('../views/HomePage')),
  },
  {
    path: '/detail/:id',
    component: asyncLoad(() => import('../views/DetailPage')),
  },
  /**
   * Exception 页面
   */
  {
    path: '/exception/404',
    component: asyncLoad(() => import('../views/Exception')),
  },
];

function generateRouteConfig (route: IRouteConfig[]) {
  return route.map(item => {
    return {
      key: item.path,
      exact: typeof item.exact === 'undefined' ? true : item.exact,
      ...item,
      component: item.component,
    };
  });
}

function asyncLoad (loader: () => Promise<any>) {
  return Loadable({
    loader,
    loading: props => {
      if (props.pastDelay) {
        return <Loading />;
      } else {
        return null;
      }
    },
    delay: 500,
  });
}

export default generateRouteConfig(routeConfig);
  • Инкапсулируя функцию asyncLoad динамически загружаемых маршрутов, можно отображать связанные компоненты только при переключении на соответствующий маршрут.

загрузка и по запросу

  • antd: Это отличная библиотека пользовательского интерфейса для реагирования, запущенная Ant Financial, которая содержит множество компонентов, которые мы часто используем.
  • Когда мы используем библиотеку antd непосредственно в этом проекте без какой-либо настройки, мы увидим в консоли следующее приглашение:
    控制台提示
  • Размер библиотеки АНТД составляет около 80 м. Полное введение этой библиотеки неизбежно повлияет на производительность сети нашего приложения. Особенно важно импортировать спрос.
  • Официальная документация (портал 👉и документация) предоставляет два способа реализации загрузки antd по требованию:
  • Этот документ принимаетbabel-plugin-importдля загрузки по запросу. Конкретные шаги описаны ниже.
  • Установитьantd:
yarn add antd
  • Установитьbabel-plugin-import:
yarn add babel-plugin-import --dev
  • Добавьте правило правила в модуль в файле config/webpack.config.js:
    module: {
      strictExportPresence: true,
      rules: [
        /* 省略代码 */
        {
          oneOf: [
            /* 省略代码 */
            /* 下面是原有代码块 */
            {
              test: /\.(js|mjs|jsx|ts|tsx)$/,
              include: paths.appSrc,
              loader: require.resolve('babel-loader'),
              options: {
                customize: require.resolve(
                  'babel-preset-react-app/webpack-overrides'
                ),
                plugins: [
                  [
                    require.resolve('babel-plugin-named-asset-import'),
                    {
                      loaderMap: {
                        svg: {
                          ReactComponent: '@svgr/webpack?-svgo,+ref![path]',
                        },
                      },
                    },
                  ],
            /* 上面是原有代码块 */
            
                  /* 下面是添加代码块 */
                  [
                    'import',{  // 导入一个插件
                      libraryName: 'antd',   // 暴露的库名
                      style: 'css' // 直接将antd样式文件动态编译成行内样式插入,就不需要每次都导入
                    }
                  ],
                ],
                /* 上面是添加代码块 */
                
                /* 下面是原有代码块 */
                cacheDirectory: true,
                cacheCompression: isEnvProduction,
                compact: isEnvProduction,
                /* 上面是原有代码块 */
              },
            },
          ],
        },
      ],
    },
  • Таким образом, загрузка компонентов antd по запросу может быть достигнута без необходимости каждый раз импортировать соответствующие файлы стилей:
import { Button } from 'antd';
  • Примечание: Поскольку в проекте реализована модульностьless, если вы хотите изменить стиль компонента antd в модуле, вам нужно использовать:global,Такие как:
:global {
  .ant-divider {
    margin: 0 0;
  }
}
  • Выше представлен полный текст. Соответствующая конфигурация прошла через мою кропотливую личную практику. Если у вас есть какие-либо вопросы, пожалуйста, оставьте сообщение.