简介

本文为React组件库建立(二)一行指令装备组件模版的具体版别,包含Debug排查部分。囊括Nx自界说插件,TailwindCss构建自建库,Ts,rollup等常识

Nx新建自界说Plugin总览

完成目标:

  • 自界说代码生成器:在你的项目,快速生成你的自界说代码片段
  • 主动增加依靠:为你的项目主动装置Taiwindcss
  • 一行指令推送你的代码到NPM

思路步骤:

  1. 经过NX Console快速初始化插件
  2. 参考和略读@nrwl/react部分源码,结合自己的需求快速自界说插件
  3. 发布Npm部分暂时运用社区插件ngx-deploy-npm

笔者现有环境装备阐明

  1. win10系统,Nvm-node,pnpm,淘宝镜像源
  2. 编辑器-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:实际运用首要也是以生成文件为主,自界说组件生成器完成很简单,考虑到能够另开一偏转讲,事例只运用官方默许的

能够先大致了解,以下是官方的模版文件

React组件搭建(二)思路分享

React组件搭建(二)思路分享

首要是运用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,接个人私活,算是一个不错的工具。