⚠️Эта статья является первой подписанной статьей сообщества Nuggets, и её перепечатка без разрешения запрещена.
Привет всем, яЛуожу 🎋, деревянный фронтенд, живущий в Ханчжоу 🧚🏻♀️, если вам понравилась моя статья 📚, вы можете помочь мне собрать духовную силу ⭐️ лайком.
предисловие
существует"У каждого фронтенда должна быть своя библиотека компонентов, как арбуз каждое лето🍉"В статье Луо Чжу привел Xiaohei к созданию проекта библиотеки компонентов с нуля, выполнил основные инженерные работы, такие как структура проекта, строительство, тестирование, документация и т. д., а также завершил иконку первого компонента. Этот выпуск продолжает тему разработки компонентов из предыдущего выпуска: Летом жарко, закажите чашку нектара Yangzhi и отправляйтесь на встречу с Луочжу по разработке кнопок. После встречи вы получите следующее:
ПС: сотрудничатьсклада такжеДокументация библиотеки компонентовЛучше прочтите эту статью!
Кнопка и психология дизайна
Как фронтенд-инженер, тот, кто до сих пор контактировал с дизайнером больше всего. Хотя я не изучил никаких инструментов дизайна, у меня есть определенное понимание дизайна и человеческой психологии.
Ло Чжу считает, что ничто не может появиться из воздуха и имеет собственное наследие. Кнопка не является исключением из широкого использования основных элементов интерфейса, кнопки есть в нашей жизни повсюду. Возьмите каштан 🌰, кнопку лифта, кнопку громкости мобильного телефона и кнопку возбуждения Сяо Ай, безвкусного одноклассника Xiaomi 9, которую нужно нажимать каждый день, чтобы пойти на работу и уйти с работы. Чтобы понять, зачем нужны кнопки, нам нужно изучить роль этих кнопок в нашей жизни.
Удовольствие от нажатия кнопки
Представьте, что клавиши клавиатуры заменены сенсорным экраном. Больше всего вас должно волновать идеальное восстановление ощущения ударных от физических клавиш. Например, Луо Чжу любит устанавливать вибрацию клавиш и звуковые эффекты с помощью виртуальной клавиатуры своего мобильного телефона. . Человеку свойственно получать удовольствие от ударов (щелчков). Кнопки имеют богатую текстуру и взаимодействие при нажатии и отпускании, что идеально удовлетворяет удовольствие людей, нажимающих на них.
практичность
От телефонов BB до Nokia и современных смартфонов физические кнопки сводятся только к клавишам регулировки громкости и кнопке питания. Клавиши голые и без опознавательных знаков, но мы просто знаем, что они делают. Только представьте, что без этого переключателя с давних времен телефон в руке просто кирпич.
Сумасшедшие подсказки пользователям для достижения скрытых мотивов
Кнопка вызова Xiao Ai на Xiaomi Mi 9 часто нажимается ошибочно, раньше я не понимал смысла такого глупого дизайна. После небольшого исследования психологии дизайна я понял. Дизайнер Xiaoai специально разработал это для повседневной жизни продукта и обучения искусственному интеллекту.
Хотя в Xiaomi Mi 10 убрали отдельную кнопку пробуждения, оригинальную кнопку питания заменили на многофункциональную. Каждый раз, когда вы хотите перезагрузить телефон, вы должны сначала возбудить Сяо Ай. Я должен сказать, что одноклассница Сяо Ай Сяоми целует ее дочь.
Tucao возвращается в Tucao, кнопка Xiaomi действительно играет роль в формировании привычек пользователей. Когда пользователь знает, что кнопка может указывать на определенную операцию или получать информацию определенного типа, в долгосрочной перспективе у пользователя сформируется привычка использования. Если операция может продолжать приносить пользу пользователям и производителям, она может сделать положение кнопки более заметным и продолжать развивать привычку пользователя кликать.
Проинструктируйте пользователя о работе
Это наиболее распространенный сценарий использования в веб-разработке, и на каждой интерактивной странице есть кнопка такого типа, которая указывает пользователю, что делать дальше. Например, отправка формы и сброс.
Хотя кнопки часто используются в качестве элементов формы, они отличаются от других элементов формы.Поскольку кнопки не требуют пояснений, им не нужна метка, чтобы объяснить их.Это так многословно.Когда вы видите кнопку, вы также должны будет чувство вкуса от дизайна, добро пожаловать, чтобы рассказать Луо Чжу о дегустации изображения ниже в области комментариев.
Тематика компонентов
Прежде чем приступить к разработке конкретных компонентов, мы должны сначала согласовать спецификацию тем компонентов. В прошлом antd-mobile-rn потратил много усилий на рефакторинг из-за проблем с дизайном. Почти все библиотеки компонентов будут предоставлять цвет и макет пользователям и разработчикам в виде переменных css.Разница между React Native в том, что стиль основан на CSS в JS, но причина та же, см.Ресурсы для дизайна, мы вытащили набор констант JavaScript:
// packages/themes
export interface Theme {
'animation-duration-base': string;
'animation-duration-fast': string;
'animation-timing-function-enter': string;
'animation-timing-function-leave': string;
'font-size-xs': number;
'font-size-sm': number;
'font-size-md': number;
'font-size-lg': number;
'font-weight-bold': number;
// 变量过多,这里仅展示部分变量
}
С помощью этих констант JS мы можем разработать систему тем. Дизайн темы на основе CSS в JS обычно реализуется на основе React Context, необходимо предоставить ThemeProvider для передачи в контексте темы ThemeConsumer, WithTheme (компонент класса более высокого порядка), withTheme (компонент функции более высокого порядка) или useTheme (React Hooks) получаются как контекст потребителей. Самостоятельно реализовать это несложно, но более актуальна задача обновления текста.cssinjs/themingЧтобы реализовать функцию, еще не поздно вернуться и построить колесо позже, если возникнет необходимость. Следующее 👇 - это то, на чем мы основаны.createTheming
функция для создания пользовательского контекста темы.
import { createTheming } from 'theming';
const context = React.createContext(defaultTheme);
const theming = createTheming(context);
export const { ThemeProvider, withTheme, useTheme } = theming;
Функции темы являются общими, поэтому я поместил возможности, связанные с темой, в
@vant-react-native/theme
публикуется в пакете.
Реализация кнопки
Стиль встроенного компонента Button в React Native фиксирован, и можно выполнить только некоторые простые настройки. И встроенный компонент Button не работает одинаково на Android и ios. Поэтому нам нужно инкапсулировать в соответствии с компонентами более низкого уровня. Сравнив элементы ant-design-mobile-rn и react-native-elements, мы выбрали тот, который использовался первым.TouchableHighlight
компоненты. Поскольку он наследуется от TouchableHighlight, тип реквизита нашего компонента выглядит следующим образом:
import { TouchableHighlightProps } from 'react-native';
interface ButtonProps extends TouchableHighlightProps {
}
тип кнопки
ВантаButtonслужба поддержкиdefault
,primary
,info
,warning
,danger
Пять типов, по умолчаниюdefault
. Теперь основное определение компонента выглядит следующим образом:
// ...
import React, { FunctionComponent } from 'react';
import { Text, View } from 'react-native';
interface ButtonProps {
type?: 'default' | 'primary' | 'info' | 'warning' | 'danger';
}
const Button: FunctionComponent<ButtonProps> = props => {
// ...
};
// ...
Чтобы адаптироваться к теме нашего компонента, стиль не может быть прописан в компоненте, а константа стиля должна быть получена через контекст. Наша идея состоит в том, чтобы сначала использоватьuseTheme
Получите тему из контекста, затем, поскольку определено много стилей, мы пишем по одному для каждого компонента.useStyle
Хуки вынесены в отдельный файл style.ts:
import { StyleSheet } from 'react-native';
import { Theme, useTheme } from '@vant-react-native/theme';
export const useStyle = props => {
const theme = useTheme<Theme>();
const getBackgroundColor = () => {
switch (props.type) {
case 'primary':
return theme['success-color'];
case 'info':
return theme['primary-color'];
case 'warning':
return theme['warning-color'];
case 'danger':
return theme['danger-color'];
default:
return theme.white;
}
};
const getTextColor = () => {
if (props.type === 'default') {
return theme.black;
} else {
return theme.white;
}
};
const getBorderRadius = () => {
if (props.round) {
return theme['border-radius-max'];
}
if (props.square) {
return 0;
}
return theme['border-radius-sm'];
};
const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor: getBackgroundColor(),
borderColor: getBorderColor(),
borderRadius: theme['border-radius-sm'],
borderWidth: theme['border-width-base'],
flexDirection: 'row',
flex: 1,
justifyContent: 'center',
opacity: 1,
paddingHorizontal: 15,
},
indicator: {
marginRight: theme['padding-xs'],
},
textStyle: {
color: getTextColor(),
fontSize: 14,
},
wrapper: {
borderRadius: theme['border-radius-sm'],
height: 44,
},
});
return styles;
};
на основеuseStyle
Мы можем завершить компонент Button, который поддерживает несколько типов:
const Button: FunctionComponent<ButtonProps> = props => {
const styles = useStyle(props);
const { style, ...restProps } = props;
return (
<TouchableHighlight style={[styles.wrapper, style]} {...restProps}>
<View style={styles.container}>
{typeof props.children === 'string' ? (
<Text style={styles.textStyle}>{props.children}</Text>
) : (
props.children
)}
</View>
</TouchableHighlight>
);
};
Примечание. Подкомпоненты могут быть строками или компонентами, поэтому вам нужно определить тип.
Эффект следующий:
обычная кнопка
Текст простой кнопки имеет цвет кнопки, а фон белый.plain
свойство устанавливает кнопку как обычную кнопку. Я исследовал antd и react-native-elements и обнаружил, что они оба определяют множество стилей, а затем вычисляют значение конкретного стиля посредством логического суждения в компоненте. Лично мне такой способ не нравится, это не полноценный CSS на JS, мой способ справиться с этим - инкапсулировать все вычисления стилей в каждом компоненте.useStyle
В хуке, например, когда вводится атрибут наивной кнопки, цвет фона контейнера, границы контейнера и цвет шрифта изменяются относительно обычной кнопки. Итак, мы вычисляем значения всех трех свойств через одну функцию. Сравнив исходный код antd, вы обнаружите, что код не только легче читается, но и объем кода меньше.
const getBackgroundColor = () => {
if (props.plain) {
return theme.white;
}
// ...
};
const getTextColor = () => {
if (props.plain) {
switch (props.type) {
case 'primary':
return theme['success-color'];
case 'info':
return theme['primary-color'];
case 'warning':
return theme['warning-color'];
case 'danger':
return theme['danger-color'];
default:
return theme['gray-3'];
}
} else if (props.type === 'default') {
return theme.black;
} else {
return theme.white;
}
};
Эффект следующий:
тонкая граница
Вант добивается тонких границ, устанавливаяhairline
Свойство может отображать тонкую рамку шириной 0,5 пикселя. Однако из-за влияния разрешения на мобильный телефон необдуманная установка 0,5 вызовет проблему совместимости, заключающуюся в том, что граница не отображается. К счастью, React Native предоставляет намStyleSheet.hairlineWidth
Постоянно, чтобы быть совместимым с самой тонкой проблемой границы, следующее официальное определение этого:
Константа hairlineWidth всегда представляет собой целое число пикселей (линия будет выглядеть тонкой, как волос) и будет пытаться соответствовать самой тонкой линии текущей платформы. Может использоваться как граница или как разделитель между двумя элементами. Однако вы не можете рассматривать его как константу, потому что разные платформы и разная плотность пикселей на экране приведут к разным результатам.
Если эмулятор увеличен, такие тонкие линии могут быть не видны.
из-заhairline
Влияет только на контейнерыborderWidth
свойства, нам не нужно писать отдельную функцию расчета стиля:
const styles = StyleSheet.create({
// ...
container: {
// ...
borderWidth: props.hairline ? theme['border-width-hairline'] : theme['border-width-base'],
},
});
Эффект следующий:
отключенное состояние
Элементы формы или сенсорные и интерактивные элементы обычно имеют отключенное состояние.Кроме того, кнопка отключена с помощью атрибута disabled, и кнопку нельзя щелкнуть в отключенном состоянии. TouchableHighlight наследуется отdisabled
свойство, нам нужно только установить некоторые стили кнопок в отключенном состоянии.Глядя на исходный код vant, мы обнаруживаем, что нам нужно только изменить прозрачность до 0,5:
const styles = StyleSheet.create({
container: {
// ...
opacity: props.disabled ? 0.5 : 1,
// ...
},
});
Эффект следующий:
состояние загрузки
Вант черезloading
Кнопка настройки атрибута находится в состоянии загрузки. В состоянии загрузки текст кнопки будет скрыт по умолчанию.loading-text
Устанавливает текст в состояние загрузки. Мы можем легко реализовать эту функцию с помощью компонента React Native ActivityIndicator:
// ...
<TouchableHighlight {...restProps}>
<View style={styles.contentWrapper}>
{props.loading ? (
<>
<ActivityIndicator size="small" color={indicatorColor} style={styles.indicator} />
{props.loadingText ? <Text style={styles.textStyle}>{props.loadingText}</Text> : null}
</>
) : null}
</View>
</TouchableHighlight>
// ...
Стиль следующий:
export const useIndicatorColor = (props: ButtonProps): string => {
const theme = useTheme<Theme>();
if (props.plain) {
switch (props.type) {
case 'primary':
return theme['success-color'];
case 'info':
return theme['primary-color'];
case 'warning':
return theme['warning-color'];
case 'danger':
return theme['danger-color'];
default:
return theme.black;
}
} else if (props.type === 'default') {
return theme.black;
} else {
return theme.white;
}
};
Эффект следующий:
форма кнопки
Кнопка по умолчанию имеет закругленные углы со значением 2, которое передается в vant.square
Установите квадратные кнопки, черезround
Установите круглые кнопки. В качестве примера мы устанавливаем стиль на основе суждения:
const getBorderRadius = () => {
if (props.round) {
return theme['border-radius-max'];
}
if (props.square) {
return 0;
}
return theme['border-radius-sm'];
};
const styles = StyleSheet.create({
container: {
borderColor: getBorderColor(),
},
wrapper: {
borderRadius: getBorderRadius(),
},
});
Эффект следующий:
размер кнопки
Antd RN поддерживает только два размера: большой и маленький, в то время как vant поддерживает четыре размера: большой, нормальный, маленький и мини. Хотя я уже очень устал это писать, а Ян Чжи Ганлу уже допил, но чтобы полностью выздороветь, мне все равно придется продолжать пить чашку кофе, чтобы продолжить печень. В соответствии с черновиком дизайна ванта мы добавляем три функции приобретения стиля и динамически указываем стиль:
const getSizeHeight = () => {
switch (props.size) {
case 'large':
return 50;
case 'small':
return 32;
case 'mini':
return 24;
default:
return 44;
}
};
const getSizePadding = () => {
switch (props.size) {
case 'small':
return 8;
case 'mini':
return 4;
default:
return 15;
}
};
const getSizeFontSize = () => {
switch (props.size) {
case 'large':
return 16;
case 'small':
return 12;
case 'mini':
return 10;
default:
return 14;
}
};
const styles = StyleSheet.create({
container: {
paddingHorizontal: getSizePadding(),
},
textStyle: {
fontSize: getSizeFontSize(),
},
wrapper: {
height: getSizeHeight(),
},
});
Эффект следующий:
нестандартный цвет
Если бы я сам не воспроизвел Vant, я не ожидал, что Button сможет играть так много цветов, и было бы непросто поддерживать так много функций, терпения и управления кодом. Конечно, метод управления стилем Луожу более экстремальный, и каждый, у кого есть хороший метод, также может обсудить его в области комментариев.
пройти черезcolor
свойство для настройки цвета кнопки. Мы можем вывести требование, независимо от типа,color
Атрибут должен всегда переопределять исходный стиль. Цвет может влиять на цвет фона, цвет шрифта и цвет границы, поэтому мы изменяемgetBackgroundColor
,getTextColor
,getBorderColor
Функция стиля может добавить следующий код в соответствующее место:
if (props.color) {
return props.color;
}
Эффект следующий:
Реализация события двойного клика
Мы наследуем многие события от встроенного компонента React Native TouchableHighlight, где onPress и onLongPress представляют щелчок и длительное нажатие соответственно. Но только событие двойного щелчка «двойной щелчок 666» не имеет имени. Событие двойного щелчка было инкапсулировано в реальном бизнесе и раньше, и на этот раз мы создали его напрямую.
Идея реализации состоит в том, чтобы отложить выполнение события клика (по умолчанию 200 миллисекунд), а затем записать количество кликов и временной интервал между двумя нажатиями, когда он распознан как второй клик и временной интервал меньше клика время задержки. Затем отмените задержку события щелчка и немедленно выполните событие двойного щелчка. Полный код выглядит следующим образом:
let lastTime = 0;
let clickCount = 1;
let timeout = null;
const _onPress = (event: GestureResponderEvent) => {
const now = Date.now();
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
props.onPress(event);
clickCount = 1;
lastTime = 0;
}, props.delayDoublePress);
if (clickCount === 2 && now - lastTime <= props.delayDoublePress) {
clearTimeout(timeout);
clickCount = 1;
lastTime = 0;
props.onDoublePress(event);
} else {
clickCount++;
lastTime = now;
}
};
Вы обнаружите, что реализация здесь сочетает в себе принципы функции защиты от сотрясения, дросселирования и счетчика.Заинтересованные друзья могут ознакомиться с принципами самостоятельно и не будут здесь подробно раскрываться.
Документация API
Документация компонента, помимо Demo, также должна показывать доступные Props, встроенные в Dumi.<API></API>
Компоненты могут автоматически генерировать документацию API на основе компонентов. Сначала мы пишем аннотацию Props следующим образом:
interface ButtonProps extends TouchableHighlightProps {
/**
* @description Can be set to primary、info、warning、danger
* @description.zh-CN 类型,可选值为 primary、info、warning、danger
*/
type?: 'default' | 'primary' | 'info' | 'warning' | 'danger';
/**
* @description Can be set to large、small、mini
* @description.zh-CN 尺寸,可选值为
*/
size?: 'large' | 'normal' | 'small' | 'mini';
}
Затем вы можете представить компоненты API в Markdown:
<API src="./index.tsx"></API>
Встроенный компонент API не обрабатывает наследование. В будущем мы настроим компонент API, который не будет здесь раскрываться.Документация по кнопкамВы можете увидеть текущий эффект:
инженерный перекрестный разговор
Поскольку в одной статье сложно охватить инженерные разработки, связанные с разработкой компонентов, нам нужно говорить об этом в каждом реальном бою.
Создание компонентов
Сяохэй: Луожу,
lerna create
Модули, созданные командой, это не то, что мы хотим.В будущем мы создадим много-много компонентов.Можем ли мы написать скаффолдинг для создания компонентных модулей?
Есть много болевых точек для использования lerna,lerna create
Нет возможности указать шаблоны для команд, учитывая, что для каждого из десятков или сотен компонентов потребуется структура проекта, конфигурация Typescript, конфигурация юнит-тестов, конфигурация Babel и другие рабочие этапы, нам нужно написать скаффолдинг.
Разбор шаблона
Когда дело доходит до синтаксического анализа шаблонов, я считаю, что все думают о синтаксическом анализе шаблонов vue-cli так же, как и я. чтениемvue-cli@2.9.6 generate.jsИз исходного кода мы можем проанализировать, что Youda реализует возможность синтаксического анализа шаблонов на основе трех пакетов: metalsmith, handlebars и консолидация. Что беспокоит, так это то, что библиотека Metalsmith не поддерживается в течение 5 лет. Подборка проектов с открытым исходным кодом Luozhu вообще очень чувствительна к обслуживанию. Основываясь на принципе сборки колес самостоятельно, я просмотрел Readme Metalsmith и обнаружил, что этот плагин не более чем Он отображает шаблоны путем рекурсивного чтения файлов, и его способность генерировать статические веб-сайты является избыточной для наших требований к разбору шаблонов.
Делай, как говоришь, в и@Линь СяошуайПосле несложного общения с одноклассниками я начал строитьhandlebars-template-compilerОсновной принцип этого колеса заключается в следующем:
- Используйте recursive-readdir для рекурсивного получения всех путей к файлам.
const files = await recursive(rootDir);
- использовать
handlebars.compile
способ рендеринга шаблона с метаданными
const content = fs.readFileSync(file).toString();
const result = handlebars.compile(content)(meta);
- использовать
fs.writeFileSync
Файл перезаписи API
Кроме того, вводяglobреализовано сопоставление с образцомexclude
настраивать и обрабатывать только указанные суффиксы (по умолчанию**/*.tpl.*
), чтобы избежать ненужного рендеринга. (PS: у NPM более 300 загрузок в неделю, кому надо, стоит попробовать😄)
Сборка интерфейса командной строки узла (@vant-react-native/scripts)
Здесь Luozhu пытается максимально лаконичным языком описать рождение строительных лесов.Исходный код находится вpackages/scriptsВ каталоге, пожалуйста, поверьте мне, если у вас нет опыта работы с CLI, с Node CLI легко начать работу. Студенты, которые были в контакте, также могут проверять и заполнять пробелы и учиться на одном или двух.
-
package.json
документbin
Поле вход в наши леса
// 指定可执行文件的位置以及别名
"bin": {
"vant": "./bin/cli.js"
},
- определение
./bin/cli.js
является исполняемым и вызываетinit
метод.
// 由于我们的脚本是 Node 编写的,所以需要指定 node 所在位置
#!/usr/bin/env node
const { init } = require('../lib');
// 这个地方参考了 create-react-native 的设计
// 本文点赞过 300,下一篇洛竹带小黑为大家带来《基于 TypeScript 重构 create-react-native》
init();
- затем в
src/index.ts
Initialize Commander, престижная среда командной строки
const init = (): void => {
const packageJson = require('../package.json');
program.version(packageJson.version).description(packageJson.description);
// ...
program.parse(process.argv);
};
- Для того, чтобы облегчить управление командами, мы поместим команды в
src/commands
каталог и черезfs.readdirSync
Регистрация динамического сканирования API.
const init = (): void => {
// 这段代码借鉴自 NeteaseCloudMusicApi 项目,作者的代码很有设计感,推荐阅读。
fs.readdirSync(path.join(__dirname, 'commands')).forEach((file: string) => {
if (!file.endsWith('.js')) return;
require(path.join(__dirname, 'commands', file));
});
// ...
};
- Наконец в
commands
Создайте новый в каталогеcreate.ts
команда записи файла
import { program } from 'commander';
program
.command('create <name> [loc]')
.description('Create a new vant-react-native package')
.action((name,loc) => {
console.log('Hello Luozhu');
})
Реализация строительных лесов
В последнем резюме мы инициализировали CLI и добавилиcreate
Команда, в этом разделе мы реализуем функцию создания лесов.
мы первыеpackages/scripts
Создайте шаблон компонента в каталоге
.
├── README.tpl.md # tpl 后缀在生成组件模板的时候会被 handlebars-template-compiler 自动去掉。
├── package.tpl.json
├── src
│ └── index.ts # 没有 tpl 后缀则不会被编译,模板很大时可以节省时间。
└── tsconfig.json
Затем мы определяем структуру данных метаданных нашего шаблона, моя структура данных здесь:
interface IMeta {
name: string;
version: string;
description: string;
author: string;
email: string;
url: string;
directory: string;
}
Имея в руках структуру данных, мы можем использовать модуль опроса, чтобы помочь пользователю вводить информацию.
import inquirer from 'inquirer';
// ...
// getQuestions 过长,感兴趣的同学可以查看:http://tny.im/UFbg
const answer: IMeta = await inquirer.prompt(getQuestions(name));
// ...
Далее мы используемtmp-promise
Модуль создает системную временную папку и копирует в нее содержимое упомянутой выше папки шаблона:
import tmp from 'tmp-promise';
import fs from 'fs-extra';
import path from 'path';
// ...
const tmpdir = await tmp.dir({ unsafeCleanup: true });
fs.copySync(path.join(__dirname, '../../template'), tmpdir.path);
Наконец, мы компилируем содержимое временной папки и копируем его в указанное место:
import htc from 'handlebars-template-compiler';
// ...
await htc<IMeta>(answer, tmpdir.path);
fs.copySync(tmpdir.path, `${process.cwd()}/packages/${locPath}`);
// ...
Бросьте эту еду, давайте посмотрим на результаты:
Github CODEOWENERS
Самое сложное в масштабных проектах с открытым исходным кодом — это не технические проблемы, а недостатка в технических мастерах никогда не будет. Самая сложная часть — это сотрудничество и пост-обслуживание. Представьте себе проект с участием сотен тысяч человек, когда идет новый PR, нормальные люди просто не в состоянии быстро найти, кому нужно проверить код. Поскольку наш vant-react-native упаковывает и поддерживает каждый компонент отдельно, эта проблема также будет возникать, когда задействовано много мелких партнеров.
И GitHub CODEOWNERS (владельцы кода) должны решить эту проблему с участием более 5000 участников.DefinitelyTypedМы видим это в проекте. Официальное определение владельца кода выглядит следующим образом:
Вы можете использовать файл CODEOWNERS, чтобы определить человека или команду, ответственную за код в репозитории. Когда кто-то изменяет код и открывает запрос на вытягивание, автоматически запрашивается проверка от владельца кода.
Файл CODEOWNERS использует шаблон, который соответствует большинству правил, используемых в файле gitignore, а расположение файла CODEOWNERS обычно находится по адресу.github/
Под содержанием.
В vant-react-native Луо Чжу является конечным лицом, отвечающим за склад, поэтому ожидается, что каждый PR может быть назначен ему для проверки. Итак, давайте попробуем, создайте новый.github/CODEOWNERS
файл и напишите следующее:
# This is a comment.
# Each line is a file pattern followed by one or more owners.
# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence,
# @youngjuning will be requested for review when someone opens a pull request.
* @youngjuning
# In this example, @doctocat owns any files in the build/logs
# directory at the root of the repository and any of its
# subdirectories.
/packages/ @luozhu1994
Как правило, если у файла есть владелец кода, вы можете увидеть, кто является владельцем кода, прежде чем открывать запрос на вытягивание. В репозитории вы можете найти файл и навести курсор на значок замка, который сообщит вам, кто является владельцем файла:
Затем мы отправляем pr, чтобы увидеть эффект:
Автоматизация пакетов NPM
Как правило, только владелец склада имеет разрешение на выпуск пакетов, но владелец поддерживает несколько учетных записей NPM одновременно, или владелец внезапно становится слишком занят, чтобы дать разрешение на выпуск другим администраторам, но неудобно информировать учетную запись NPM. Что я должен делать? Ответ заключается в создании компакт-диска пакета NPM (непрерывное развертывание), и компании обычно реализуют эту функцию на основе Gitlab или собственных платформ. Как проект с открытым исходным кодом, мы, конечно, используем GitHub Action.
Для обычных однопакетных проектов используйтеnpm-publishилиnpm-publish-actionОб этих двух действиях GitHub говорить непросто. Однако готового плагина для многоупаковочного единого склада на базе lerna нет, как обычно, давайте посмотрим на шаги собственной реализации:
- Определите, начинается ли сообщение фиксации с
chore(release):
началоЧерез действие GitHub
startsWith(github.event.head_commit.message, 'chore(release):')
выполнить - Войти с аутентификацией токена публикации NPM
пройти через
npm config set //registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}
Сертификация - воплощать в жизнь
lerna publish from-package --yes
выпускатьнужно выполнять локально
lerna version
Усовершенствованная версия команды серии
Полная реализация GitHub Action выглядит следующим образом:
name: npm-publish
on:
push:
branches:
- main
jobs:
npm-publish:
runs-on: ubuntu-latest
if: startsWith(github.event.head_commit.message, 'chore(release):')
steps:
- uses: actions/checkout@v2
- uses: c-hive/gha-yarn-cache@v2 # 缓存 node_modules 加快构建速度
- name: Install Packages
run: yarn install --registry=https://registry.npmjs.org/
- name: Authenticate with Registry
run: |
npm config set //registry.npmjs.org/:_authToken=${NPM_TOKEN}
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Publish package
run: lerna publish from-package --yes
Чтобы вовремя получать уведомления после релиза, Луожу использовалpeter-evans/commit-comment
Плагин прокомментировал соответствующий коммит после неудачного или успешного выпуска, чтобы мы могли получать электронные письма и уведомления на сайте.
- name: Create commit comment after publish successfully
if: ${{ success() }}
uses: peter-evans/commit-comment@v1
with:
body: |
Hello Dear @youngjuning. This commit has been publish to NPM successfully.
> Created by [commit-comment][1]
[1]: https://github.com/peter-evans/commit-comment
- name: Create commit comment after publish unsuccessfully
if: ${{ failure() }}
uses: peter-evans/commit-comment@v1
with:
body: |
Hello Dear @youngjuning. This commit has been publish to NPM unsuccessfully.
> Created by [commit-comment][1]
[1]: https://github.com/peter-evans/commit-comment
Спасибо
На момент публикацииКаждый интерфейс заслуживает собственной библиотеки компонентов, как арбуз каждое лето 🍉Он получил почти 1600 лайков и более 40 000 просмотров📖, еще раз спасибо за вашу поддержку, поддержку редактора Зои, босса Юин за перепечатку, репост друзей и собственную настойчивость.
последние хорошие статьи
- Каждый интерфейс заслуживает собственной библиотеки компонентов, как арбуз каждое лето 🍉
- Создание и поддержка многопакетных проектов JavaScript на основе lerna
- Сделайте это одним куском Обычные коммиты
- Лучшие фреймворки Node.js для использования в 2021 году
- Интервью React должно знать серию
- Серия учебников по языку Go
Эта статья была впервые опубликована в "Колонка самородков", синхронизированный с официальными аккаунтами "Program Life" и "Официальный сайт Луожу".