Опубликуйте реагирующий компонент, используя npm (наступив на пит-практику)

React.js

предисловие

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

  • Следующее содержание в основном включает:

    • Опубликуйте скаффолдинг для реагирующих компонентов.
    • Компоненты развития.
    • Упакуйте компонент и вставьте упакованный модуль компонента в тестовый проект, чтобы проверить функцию компонента.
    • Опубликовать вNPM.

строительные леса

Создать проект

  • Сначала создайте папку проекта и используйтеnpm initКоманда создает исходный файл конфигурации package.json Конкретные команды следующие:
mkdir react-component-npm-cli
cd react-component-npm-cli
npm init
  • в настоящее время используетnpm initКогда команда будет выполнена, нам будет предложено ввести имя проекта, номер версии, автора и т. д., и мы можем нажать Enter до упора и изменить его позже. Или напрямую используйте следующую команду, чтобы принять конфигурацию по умолчанию, а затем изменить ее в соответствии с вашими потребностями:
npm init -y
  • После завершения этого шага в папку нашего проекта будет добавлен новый файл package.json. Затем усовершенствуйте скаффолдинг и создайте следующую структуру каталогов:
├── config  # webpack配置
     ├── webpack.base.js # 公共配置
     ├── webpack.dev.config.js # 开发环境配置
     └── webpack.prod.config.js # 打包发布环境配置
├── example # 开发时预览代码
       ├── src # 示例代码目录
            ├── app.js # 入口 js 文件
            └── index.html # 入口 html 文件
├── lib # 组件打包结果目录
├── node_modules # 安装依赖时自动生成
├── src # 组件源代码目录
     ├── index.css # 组件样式
     └── index.js  # 组件源代码
├── .babelrc # babel 配置
├── .npmignore # 指定发布 npm 的时候需要忽略的文件和文件夹
├── README.md
└── package.json

Установить зависимости

  • Сначала установите зависимости, связанные с реакцией:
npm i react react-dom -D
  • Затем установите зависимости, связанные с компиляцией babel:
npm i @babel/cli @babel/core @babel/preset-env @babel/preset-react -D
  • Этот проект использует webpack для создания, использует webpack-dev-server в качестве локального сервера разработки и использует webpack-merge для слияния конфигураций webpack, поэтому используйте следующие команды для установки связанных зависимостей:
npm i webpack webpack-cli webpack-dev-server webpack-merge -D
  • В то же время используйте babel-loader для компиляции jsx и используйте MiniCssExtractPlugin для извлечения css.Команда установки выглядит следующим образом:
npm i babel-loader mini-css-extract-plugin -D
  • Наконец, установите style-loader и css-loader, которые вместе позволяют нам встраивать таблицы стилей в js-файлы, упакованные webpack (для среды разработки).
  • После выполнения вышеуказанной команды информация о зависимостях, содержащаяся в package.json, выглядит следующим образом:
{
    "devDependencies": {
    // babel 用于将 es6+ 的代码转换成 es5
    "@babel/cli": "^7.5.5",
    "@babel/core": "^7.5.5",
    "@babel/preset-env": "^7.5.5", // 根据目标环境实现按需转码
    "@babel/preset-react": "^7.0.0", // 让babel支持react语法
    "babel-loader": "^8.0.6", // 编译 jsx
    "css-loader": "^3.2.0", // 将 css 装换成js
    "mini-css-extract-plugin": "^0.8.0", // 提取css
    "react": "^16.9.0",
    "react-dom": "^16.9.0",
    "style-loader": "^1.0.0", // 将 css 装换成js
    "webpack": "^4.39.3",
    "webpack-cli": "^3.3.7", // webpack4之后需要额外安装webpack-cli
    "webpack-dev-server": "^3.8.0", // 开发时预览组件所用的服务,在文件变化时会自动刷新页面
    "webpack-merge": "^4.2.2" // 用于合并webpack配置
  },
  "dependencies": {}
}

Настроить webpack и babel

  • Как показано в приведенной ранее структуре каталогов, в каталоге config мы создаем 3 файла конфигурации веб-пакета:
    • общедоступный файл конфигурации:webpack.base.js.
    • Конфигурационный файл среды разработки:webpack.dev.config.js.
    • Файл конфигурации среды выпуска пакета:webpack.prod.config.js.
  • Так как часть конфигурации вебпака является общедоступной и повторяется при разработке и упаковке релиза, эта часть конфигурации вынесена отдельно и помещена вwebpack.base.js, содержимое файла следующее:
module.exports = {
  module: {
    rules: [
      {
        // 使用 babel-loader 来编译处理 js 和 jsx 文件
        test: /\.(js|jsx)$/,
        use: "babel-loader",
        exclude: /node_modules/
      }
    ]
  },
};
  • Конфигурация веб-пакета, используемая во время разработки, написана наwebpack.dev.config.js, содержание следующее:
const path = require('path');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.base.js'); // 引用公共配置

const devConfig = {
  mode: 'development', // 开发模式
  entry: path.join(__dirname, "../example/src/app.js"), // 项目入口,处理资源文件的依赖关系
  output: {
    path: path.join(__dirname, "../example/src/"),
    filename: "bundle.js", // 使用webpack-dev-sevrer启动开发服务时,并不会实际在`src`目录下生成bundle.js,打包好的文件是在内存中的,但并不影响我们使用。
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        exclude: /\.min\.css$/,
        loader: ['style-loader','css-loader?modules'],
      },
      {
        test: /\.min\.css$/,
        loader: ['style-loader','css-loader'],
      },
    ]
  },
  devServer: {
    contentBase: path.join(__dirname, '../example/src/'),
    compress: true,
    host: '127.0.0.1', // webpack-dev-server启动时要指定ip,不能直接通过localhost启动,不指定会报错
    port: 3001, // 启动端口为 3001 的服务
    open: true // 自动打开浏览器
  },
};
module.exports = merge(devConfig, baseConfig); // 将baseConfig和devConfig合并为一个配置
  • Конфигурация веб-пакета, используемая, когда компоненты упаковки написаны наwebpack.prod.config.js, содержание следующее:
const path = require('path');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.base.js'); // 引用公共的配置
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // 用于将组件的css打包成单独的文件输出到`lib`目录中

const prodConfig = {
  mode: 'production', // 开发模式
  entry: path.join(__dirname, "../src/index.js"),
  output: {
    path: path.join(__dirname, "../lib/"),
    filename: "index.js",
    libraryTarget: 'umd', // 采用通用模块定义
    libraryExport: 'default', // 兼容 ES6 的模块系统、CommonJS 和 AMD 模块规范
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        loader: [MiniCssExtractPlugin.loader,'css-loader?modules'],
      },
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "main.min.css" // 提取后的css的文件名
    })
  ],
  externals: { // 定义外部依赖,避免把react和react-dom打包进去
    react: {
      root: "React",
      commonjs2: "react",
      commonjs: "react",
      amd: "react"
    },
    "react-dom": {
      root: "ReactDOM",
      commonjs2: "react-dom",
      commonjs: "react-dom",
      amd: "react-dom"
    }
  },
};

module.exports = merge(prodConfig, baseConfig); // 将baseConfig和prodConfig合并为一个配置
  • После завершения написания конфигурационного файла webpack он должен находиться в package.jsonscriptsНастройте соответствующие команды запуска, упаковки и публикации в полях.Содержимое скрипта, добавленное в package.json, выглядит следующим образом:
// package.json
...
  "scripts": {
    "start": "webpack-dev-server --config config/webpack.dev.config.js", // 使用webpack-dev-server启动一个开发服务用于预览组件效果
    "build": "webpack --config config/webpack.prod.config.js", // 打包组件
    "pub": "npm run build && npm publish", // 打包组件并发布到npm
  },
...

настроить бабел

  • Нам нужно использовать babel для компиляции нашего кода в версию es5. Встроен в корневой каталог проекта.babelrcДобавьте в файл следующее:
{
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}
  • Вышеизложенное завершает процесс строительства строительных лесов, после чего можно приступать к разработке компонентов.

компоненты разработки

  • Чтобы продемонстрировать, я создам простой в каталоге src具有样式компоненты, которые вы можете изменить в соответствии с вашими потребностями,index.jsКонкретное содержимое файла выглядит следующим образом:
<!-- src/index.js -->
import React from 'react';
import * as styles from './index.css';
class ReactDemo extends React.Component{
  render () {
    return <div className={styles.wrapper}>hello world</div>
  }
}
export default ReactDemo;
  • файл стиляindex.cssКонкретное содержимое файла выглядит следующим образом:
<!-- src/index.css -->
.wrapper{
  background: red;
}
  • Для того, чтобы просмотреть эффект компонента в режиме реального времени во время разработки, вам необходимо создать новый в каталоге примеров.index.htmlиapp.jsдва файла,index.htmlСодержание следующее:
<!-- examples/src/index.html -->
<html>
<head>
    <title>My First React Component</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
  <div id="root"></div>
  <script src="bundle.js"></script> <!-- 这句十分重要 -->
</body>
</html>
  • Внимательные одноклассники ⚠️ обратят внимание ⚠️ на,index.htmlфайл с именемbundle.jsПричина в том, что в процессе разработки (используя webpack-dev-sevrer для запуска службы разработки) он фактически не генерируется в каталоге srcbundle.js, запакованный файл находится в памяти.Если вы хотите просмотреть эффект в реальном времени, вам нужно ввести его в html (также можно использовать инжект плагина html-webpack-plugin, который здесь подробно объясняться не будет ).
  • app.jsСодержание следующее:
/*** examples/src/app.js ***/
import React from 'react'
import { render } from 'react-dom'
import ReactDemo from '../../src' // 引入组件

const App = () => <ReactDemo />
render(<App />, document.getElementById('root'))
  • Теперь выполните в корневом каталогеnpm start, когда вы увидите результат, как показано на рисунке ниже, это означает, что компиляция прошла успешно:
    编译成功结
  • посетить в это время127.0.0.1:3001Результат вы можете увидеть на следующем рисунке:

Упаковка компонентов и функциональное тестирование

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

Упаковка компонентов

  • Команда для упаковки компонента была добавлена ​​в package.json ранее, однако при выполненииnpm run buildРаньше его также нужно было модифицировать в package.jsonmainПоле, которое используется для объявления входного файла компонента.

разработчик вimport Наши компоненты будут представлены, когдаmainв полеexportСодержание.

  • На данный момент полное содержимое моего package.json выглядит следующим образом. Для простоты понимания я добавил комментарий. Если вы хотите использовать его напрямую, удалите комментарий:
{
  "name": "react-demo-component", // 发布的 npm 包的名字,确保独一无二(先在 npm 上搜,若与已有的包重名会报错)
  "version": "1.0.0", // npm 包版本
  "description": "A test component demo", // 包的描述
  "main": "lib/index.js", // *重点*:声明组件的入口文件
  "scripts": { // 执行脚本
    "start": "webpack-dev-server --config config/webpack.dev.config.js", // 使用webpack-dev-server启动一个开发服务用于预览组件效果
    "build": "webpack --config config/webpack.prod.config.js", // 打包组件
    "pub": "npm run build && npm publish", // 打包组件并发布到npm
  },
  "keywords": [ // 关键字(在npm网站上搜索 npm 包的关键词)
    "react",
    "hello world"
  ],
  "author": "feSmallBlack", // npm 包的作者
  "license": "ISC", // 版权许可证
  "devDependencies": { // 开发环境依赖
    "@babel/cli": "^7.5.5",
    "@babel/core": "^7.5.5",
    "@babel/preset-env": "^7.5.5",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.6",
    "css-loader": "^3.2.0",
    "mini-css-extract-plugin": "^0.8.0",
    "react": "^16.9.0",
    "react-dom": "^16.9.0",
    "style-loader": "^1.0.0",
    "webpack": "^4.39.3",
    "webpack-cli": "^3.3.7",
    "webpack-dev-server": "^3.8.0",
    "webpack-merge": "^4.2.2"
  },
  "dependencies": {} 生产环境依赖
}
  • Далее вы можете использоватьnpm run buildУпакуйте наши разработанные компоненты, и следующие результаты свидетельствуют об успешной упаковке:

打包成功的结果

  • На этом этапе в каталоге lib корневого каталога проекта появятся следующие два файла:
    lib目录下的内容
  • Эти два файла представляют собой пакеты, которые мы хотим опубликовать.

Функциональное тестирование компонентов

  • Хотя мне очень хотелось попробовать, я не мог не отправить посылку, но! Перед выдачей пакета, чтобы нести ответственность за всех и за себя и избежать частых операций по выводу средств, лучше всего сначала попробовать собственные компоненты.
  • мы можем использоватьnpm linkВнесите упакованные компоненты в глобальные node_modules, соответствующие команды выглядят следующим образом:
// At development directory
npm run build
npm link
  • воплощать в жизньnpm linkРезультат после команды следующий:
    npm link的结果
  • Попробуйте это в файле example/src/app.js, соответствующие команды выглядят следующим образом:
// At development directory
cd example/src
npm link react-demo-component
  • Затем измените содержимое example/src/app.js:
/*** examples/src/app.js ***/
import React from 'react'
import { render } from 'react-dom'
import ReactDemo from 'react-demo-component';
import 'react-demo-component/lib/main.min.css'; // !需要引入样式!
// import ReactDemo from '../../src'

const App = () => <ReactDemo />
render(<App />, document.getElementById('root'))
  • Если появится следующий результат, это означает, что проверка функции упакованного компонента пройдена:
    验证功能结果
  • Далее я представлю последнюю часть радостных новостей, публикуя компоненты дляNPM!

опубликовать компонент

настроить.npmignore

  • Если файл .npmignore не прописан в проекте, его нужно добавить в package.jsonfilesполе, используемое для объявления того, что оно будет опубликовано вNPMдокумент. Если этот параметр опущен, все файлы, включая исходный код, будут загружены наNPM.
  • В этой статье используется метод записи файлов .npmignore для публикации только упакованного кода компонента. Конкретное содержимое файла .npmignore выглядит следующим образом:
# 指定发布 npm 的时候需要忽略的文件和文件夹
# npm 默认不会把 node_modules 发上去
config # webpack配置
example # 开发时预览代码
src # 组件源代码目录
.babelrc # babel 配置

Зарегистрируйте npm-аккаунт

  • Чтобы опубликовать пакет npm, нам нужно добавить учетную запись npm с помощью следующей команды (если вы уже добавили этот шаг, вы можете его пропустить):
npm adduser
  • После ввода имени пользователя, пароля и адреса электронной почты в соответствии с запросом, если в командной строке выводятсяLogged in as <user> on https://registry.npmjs.org/, это означает, что регистрация учетной записи и вход в систему прошли успешно. npm запишет и временно сохранит информацию для входа/Users/<user>/.npmrcв файле конфигурации.
  • Если у вас уже есть учетная запись npm, вы можете использовать ее напрямую.npm loginАвторизоваться.
  • ⚠️Примечание: поскольку использование официального источника npm для установки пакетов в Китае относительно медленное, в основном, адрес источника npm будет изменен при внутренней разработке.Перед отправкой пакета вы должны переключиться на источник npm, иначе следующая ошибка будет сообщено:
error: no_perms Private mode enable, only admin can publish this module
  • можно использоватьnpm config listПроверьте текущий используемый адрес источника.Если это не официальный адрес источника, вы можете переключить источник npm с помощью следующей команды:
npm config set registry http://registry.npmjs.org
  • Вы также можете использовать nrm для управления исходным кодом npm.Из-за длины этой статьи мы не будем объяснять это здесь (портал 👉:Управление исходным кодом для NPM с помощью NRM)
  • После успешного перехода на официальный источник мы можем использовать следующую команду для публикации наших компонентов вNPM:
npm run pub
// 上面的命令效果与下面的命令效果一样
npm build
npm publish
  • Когда вы увидите следующие результаты, это означает, что пакет был успешно отправлен:
    发包成功结果
  • На этом этапе вы также можете просмотреть пакет, который вы только что выпустили в npm:
    npm结果
  • Другие также могут скачать ваш пакет с помощью следующей команды:
npm i react-demo-component // 假设你的包名字叫react-demo-component
  • Инструкции:
// 组件中引入
import ReactDemo from 'react-demo-component';
// 如果给组件写了样式,需要手动导入css文件
import 'react-demo-component/lib/main.min.css';
  • Отменить публикацию (желательно нет, другие могли скачать ваш пакет):
npm unpublish react-demo-component --force // 假设你的包名字叫react-demo-component
  • Если вы хотите узнать о распределении компонентов vue, хорошая доставка текста 👉Вы можете написать свой собственный пакет npm.
  • Адрес источника:GitHub.com/okita хо…
  • Выше представлен полный текст. Соответствующая конфигурация прошла через мою кропотливую личную практику. Если у вас есть какие-либо вопросы, пожалуйста, оставьте сообщение.