简介
本文为React组件库建立(二)一行指令装备组件模版的具体版别,包含Debug排查部分。囊括Nx自界说插件,TailwindCss构建自建库,Ts,rollup等常识
Nx新建自界说Plugin总览
完成目标:
- 自界说代码生成器:在你的项目,快速生成你的自界说代码片段
- 主动增加依靠:为你的项目主动装置Taiwindcss
- 一行指令推送你的代码到NPM
思路步骤:
- 经过NX Console快速初始化插件
- 参考和略读@nrwl/react部分源码,结合自己的需求快速自界说插件
- 发布Npm部分暂时运用社区插件ngx-deploy-npm
笔者现有环境装备阐明
- win10系统,Nvm-node,pnpm,淘宝镜像源
- 编辑器-Vscode
扩展官方插件
新建插件
- 装置官方插件帮手
- 在lib下新建插件库
- 在插件库下新建一个生成器
具体指令:
pnpm add -D @nrwl/nx-plugin
nx generate @nrwl/nx-plugin:plugin nx-plugin-ui --importPath=@taibui/devkit
nx generate @nrwl/nx-plugin:generator library --project=nx-plugin-ui
> NX Running global Nx CLI with PNPM may have issues.
> NX Generating @nrwl/nx-plugin:generator
CREATE libs/nx-plugin-ui/src/generators/library/files/src/index.ts__template__
CREATE libs/nx-plugin-ui/src/generators/library/generator.spec.ts
CREATE libs/nx-plugin-ui/src/generators/library/generator.ts
CREATE libs/nx-plugin-ui/src/generators/library/schema.d.ts
CREATE libs/nx-plugin-ui/src/generators/library/schema.json
UPDATE libs/nx-plugin-ui/generators.json
界说插件shema
在刚创立的生成器-library下界说schema
具体思路
1.扩展自@newl/react。只需仿制官方插件的就好了
2.咱们的自界说需求仅需在impl中完成,只需小幅度界说schema
功用拆分和完成
1。根据官方插件的,运用库生成器生成一个库
2. 为了调试和初始化,运用组件生成器生成一个Test组件(第一个生成器也在src根目录生成了组件)
3. 自界说需求:改进官方插件的装备Storybook后的工作流(在storybook装备文件引进css)
自界说需求完成思路
创立一个React库
只需调用官方保护的React插件,传入契合个人需求的参数,事例是限制rollup打包和移除默许生成的组件,强制可发布
import {
libraryGenerator,
...
} from '@nrwl/react';
const initLibrary = await libraryGenerator(tree, {
...options,
unitTestRunner: 'jest',
bundler: 'rollup',
publishable: true,
buildable: true,
component: false,
});
react组件生成器
在项目初始化的时候生成一个Test组件,默许官方是在进口文件同级目录生成一个组件库同名的组件
const genComponent = await componentGenerator(tree, {
name: 'Test',
project: options.name,
style: 'none',
//默许导出进口文件
export: true,
});
tips:实际运用首要也是以生成文件为主,自界说组件生成器完成很简单,考虑到能够另开一偏转讲,事例只运用官方默许的
能够先大致了解,以下是官方的模版文件
首要是运用generateFiles
,略微改动就能创立自界说组件生成器
storybook装备
限制webpack打包。默许装备文件为ts,不新建测试app
假如装备为ts,js摇摆,可能要做些兼容处理,由于后期引进css文件要修正装备文件
const setStorybookForLib = await storybookConfigurationGenerator(tree, {
name: options.name,
configureCypress: false,
// Automatically generate *.stories.ts files for components declared in this project
generateStories: true,
generateCypressSpecs: false,
bundler: 'webpack',
tsConfiguration: true,
});
// 装备文件为ts和js的差异
// 更新 ./storybook/previews.ts 或许 ./.storybook/preview.js
const storybookConfigPath = joinPathFragments(
projectRoot,
options.storyTsConfiguration
? '.storybook/preview.ts'
: '.storybook/preview.js'
);
const storybookConfigSource = host.read(storybookConfigPath, 'utf-8');
if (storybookConfigSource !== null && cssSource !== null) {
const changes = applyChangesToString(storybookConfigSource, [
{
type: ChangeType.Insert,
index: 0,
text: `import '../src/styles.css';\n`,
},
]);
host.write(storybookConfigPath, changes);
}
装备tailwindcss
由于是根据官方的插件修正,这里有个坑,插件会检测你的目录是否有css款式文件。而咱们装备组件库时,确实没有css文件。运用tailwind,也就是在打包时在进口文件引进。假如不先处理,也不影响本地开发(条件装备好Storybook),仅仅是友爱提示你没有装备好tailwind
// 在装备tailwindcss之前,先在项目src目录下创立一个styles.css文件
createFiles(tree, normOptions);
// 正常为lib装备tailwindcss
const setTaikwindForLib = await setupTailwindGenerator(tree, {
project: options.name,
// The name of the target used to build the project. This option is not needed in most cases
buildTarget: `${options.name}-build`,
});
// 官方插件部分源码
const knownLocations = [
// Plain React
'src/styles.css',
'src/styles.scss',
'src/styles.styl',
'src/styles.less',
// Next.js
'pages/styles.css',
'pages/styles.scss',
'pages/styles.styl',
'pages/styles.less',
];
if (stylesPath) {
const content = tree.read(stylesPath).toString();
tree.write(
stylesPath,
`@tailwind base;\n@tailwind components;\n@tailwind utilities;\n${content}`
);
} else {
logger.warn(
stripIndents`
Could not find stylesheet to update. Add the following imports to your stylesheet (e.g. styles.css):
@tailwind base;
@tailwind components;
@tailwind utilities;
更新文件
运用装备tailwindcss理论上插件会帮你引进tailwind款式,可是15.8的nx插件还是不能直接装备taiwind
首要思路,Nx修正更新json文件是很简单的(供给帮手函数updateJson
),可是修正ts,js文件,根本要靠自己完成,略微杂乱的,比方增加一个路由组件,主动更新路由装备,估量就要上AST了。
事例仅仅修正进口文件,根本上仅仅在第一行 或许最后一行插入字符,
// 更新文件
addExportsToBarrel(tree, normOptions);
export default function addExportsToBarrel(
host: Tree,
options: NormalizedSchema
) {
if (!tsModule) {
tsModule = ensureTypescript();
}
const project = getProjects(host).get(options.name);
const {
sourceRoot: projectSourceRoot,
projectType,
root: projectRoot,
} = project;
const isApp = projectType === 'application';
const indexFilePath = joinPathFragments(projectSourceRoot, 'index.ts');
const indexSource = host.read(indexFilePath, 'utf-8');
if (!isApp) {
const cssFilePath = joinPathFragments(projectSourceRoot, 'styles.css');
const cssSource = host.read(cssFilePath, 'utf-8');
if (indexSource !== null && cssSource !== null) {
const changes = applyChangesToString(indexSource, [
{
type: ChangeType.Insert,
index: 0,
text: `import './styles.css';\n`,
},
]);
host.write(indexFilePath, changes);
}
新建Rollup和更新project文件
经过generateFiles
新建文件,要注意的是,要更新Nx程式级 | 库级的project.json
事例修正的是履行器的装备
你的Nx指令都注册在该装备文件上
tips 旧版别的nx会在根目录有个workspace.json,新版别现在已经抛弃了,用project.json取代它的功用
// 新建 custom-rollup.config.js
generateFiles(
tree,
joinPathFragments(__dirname, 'files/rollup/'),
joinPathFragments(normOptions.projectRoot),
{
template: '',
}
);
// 更新project.json
updateProject(tree, normOptions);
export default function updateProject(tree: Tree, options: NormalizedSchema) {
const project = readProjectConfiguration(tree, options.name);
project.targets = project.targets || {};
project.targets.build = {
...project.targets.build,
options: {
...project.targets.build.options,
rollupConfig: `${options.projectRoot}/custom-rollup.config.js`,
},
};
updateProjectConfiguration(tree, options.name, project);
}
tailwind其它装备
tailwind的prettier插件
装置插件依靠 等同于履行 yarn add prettier-plugin-tailwindcss
事例挑选的是删掉原有装备文件,由于修正js | ts 略杂乱,初始化项目也没有什么装备,上AST不如新建
const addPrettierTailwindPlugin = addDependenciesToPackageJson(
tree,
{},
{
'prettier-plugin-tailwindcss': '^0.2.7',
}
);
// 删去原有的tailwindcss装备文件
try {
tree.exists(`${normOptions.projectRoot}/tailwind.config.js`) &&
tree.delete(`${normOptions.projectRoot}/tailwind.config.js`);
} catch (e) {
throw new Error('删去原有的tailwindcss装备文件失败');
}
新建两个tailwind装备文件
工作区级和程式级的装备文件
// 新建tailwind.config.js
generateFiles(
tree,
joinPathFragments(__dirname, 'files/taiwind/'),
joinPathFragments(normOptions.projectRoot),
{
template: '',
configRelativeUrl: offsetFromRoot(normOptions.projectRoot),
}
);
// 检查工作区是否存在装备文件taiwind-worksapce-preset.config.js,否则创立
if (
!tree.exists(
joinPathFragments(tree.root, 'taiwind-worksapce-preset.config.js')
)
) {
generateFiles(
tree,
joinPathFragments(__dirname, 'files/twpreset/'),
joinPathFragments(workspaceRoot),
{
template: '',
}
);
logger.warn("Don't forget to check the preset to your tailwind.config.js");
}
这里凭借offsetFromRoot(normOptions.projectRoot)
获取两个文件的相对方位,这样程式级装备文件才干引用对
module.exports = {
presets: [require('<%= configRelativeUrl %>taiwind-worksapce-preset.config.js')],
content: [
...
],
...
plugins: [],
};
开发经验
经过–dry-run 不断调试,总能完成自界说插件
pnpm exec nx g @taibui/devkit --dry-run
总结
Nx暴露的许多帮手函数,能让咱们十分简单的在工作区管理文件,社区活跃。目前底层是TS,可是有计划迁移其它计划,目前.net 和 Go也能脱离NPM运用Nx,接个人私活,算是一个不错的工具。