Skip to content

Commit

Permalink
feat(react): add Vite bundler option for buildable libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
jaysoo authored and Jack Hsu committed Nov 24, 2022
1 parent 61f6e2d commit c2a336a
Show file tree
Hide file tree
Showing 32 changed files with 267 additions and 67 deletions.
14 changes: 12 additions & 2 deletions docs/generated/packages/react.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@
"type": "boolean",
"default": false
},
"skipBabelConfig": {
"description": "Do not generate a root babel.config.json (if babel is not needed).",
"type": "boolean",
"default": false
},
"js": {
"type": "boolean",
"default": false,
Expand Down Expand Up @@ -243,7 +248,7 @@
"bundler": {
"description": "The bundler to use.",
"enum": ["vite", "webpack"],
"x-prompt": "Which bundler do you want to use?",
"x-prompt": "Which bundler do you want to use to build the application?",
"default": "webpack"
}
},
Expand Down Expand Up @@ -418,11 +423,16 @@
"description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.",
"type": "boolean"
},
"bundler": {
"description": "The bundler to use.",
"enum": ["vite", "rollup"],
"default": "rollup"
},
"compiler": {
"type": "string",
"enum": ["babel", "swc"],
"default": "babel",
"description": "Which compiler to use."
"description": "Which compiler to use. Does not apply if bundler is set to Vite."
},
"skipPackageJson": {
"description": "Do not add dependencies to `package.json`.",
Expand Down
6 changes: 6 additions & 0 deletions docs/generated/packages/vite.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@
"x-dropdown": "project",
"x-prompt": "What is the name of the project to set up a webpack for?"
},
"includeLib": {
"type": "boolean",
"description": "Add a library build option.",
"default": false,
"x-prompt": "Does this project contain a buildable library?"
},
"uiFramework": {
"type": "string",
"description": "UI Framework to use for Vite.",
Expand Down
5 changes: 5 additions & 0 deletions docs/generated/packages/web.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@
"description": "Do not add dependencies to `package.json`.",
"type": "boolean",
"default": false
},
"skipBabelConfig": {
"description": "Do not generate a root babel.config.json (if babel is not needed).",
"type": "boolean",
"default": false
}
},
"required": [],
Expand Down
16 changes: 16 additions & 0 deletions e2e/react/src/react-package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,4 +252,20 @@ export async function h() { return 'c'; }
}).toThrow();
}, 250000);
});

it('should support bundling with Vite', async () => {
const libName = uniq('lib');

runCLI(
`generate @nrwl/react:lib ${libName} --buildable --bundler=vite --no-interactive`
);

const result = await runCLIAsync(`build ${libName}`);

expect(result).toMatch(/Vite builder finished/);
checkFilesExist(
`dist/libs/${libName}/index.js`,
`dist/libs/${libName}/index.mjs`
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ describe('app', () => {
compiler: 'babel',
e2eTestRunner: 'cypress',
skipFormat: false,
unitTestRunner: 'jest',
name: 'myApp',
linter: Linter.EsLint,
style: 'css',
Expand Down
9 changes: 6 additions & 3 deletions packages/react/src/generators/application/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export async function applicationGenerator(host: Tree, schema: Schema) {
const initTask = await reactInitGenerator(host, {
...options,
skipFormat: true,
skipBabelConfig: options.bundler === 'vite',
});

tasks.push(initTask);
Expand Down Expand Up @@ -108,9 +109,11 @@ export async function applicationGenerator(host: Tree, schema: Schema) {

const cypressTask = await addCypress(host, options);
tasks.push(cypressTask);
const jestTask = await addJest(host, options);
tasks.push(jestTask);
updateSpecConfig(host, options);
if (options.unitTestRunner === 'jest') {
const jestTask = await addJest(host, options);
tasks.push(jestTask);
updateSpecConfig(host, options);
}
const styledTask = addStyledModuleDependencies(host, options.styledModule);
tasks.push(styledTask);
const routingTask = addRouting(host, options);
Expand Down
30 changes: 15 additions & 15 deletions packages/react/src/generators/application/lib/normalize-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,7 @@ export function normalizeOptions(

assertValidStyle(options.style);

if (options.bundler === 'vite') {
options.unitTestRunner = 'vitest';
}

options.routing = options.routing ?? false;
options.strict = options.strict ?? true;
options.classComponent = options.classComponent ?? false;
options.unitTestRunner = options.unitTestRunner ?? 'jest';
options.e2eTestRunner = options.e2eTestRunner ?? 'cypress';
options.compiler = options.compiler ?? 'babel';
options.bundler = options.bundler ?? 'webpack';
options.devServerPort ??= findFreePort(host);

return {
const normalized = {
...options,
name: names(options.name).fileName,
projectName: appProjectName,
Expand All @@ -63,5 +50,18 @@ export function normalizeOptions(
fileName,
styledModule,
hasStyles: options.style !== 'none',
};
} as NormalizedSchema;

normalized.routing = normalized.routing ?? false;
normalized.strict = normalized.strict ?? true;
normalized.classComponent = normalized.classComponent ?? false;
normalized.compiler = normalized.compiler ?? 'babel';
normalized.bundler = normalized.bundler ?? 'webpack';
normalized.unitTestRunner =
normalized.unitTestRunner ??
(normalized.bundler === 'vite' ? 'vitest' : 'jest');
normalized.e2eTestRunner = normalized.e2eTestRunner ?? 'cypress';
normalized.devServerPort ??= findFreePort(host);

return normalized;
}
2 changes: 2 additions & 0 deletions packages/react/src/generators/application/lib/set-defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export function setDefaults(host: Tree, options: NormalizedSchema) {
style: options.style,
unitTestRunner: options.unitTestRunner,
linter: options.linter,
bundler: options.bundler,
...prev.application,
},
component: {
Expand All @@ -40,6 +41,7 @@ export function setDefaults(host: Tree, options: NormalizedSchema) {
style: options.style,
unitTestRunner: options.unitTestRunner,
linter: options.linter,
bundler: options.bundler,
...prev.library,
},
},
Expand Down
3 changes: 2 additions & 1 deletion packages/react/src/generators/application/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export interface Schema {
skipFormat: boolean;
directory?: string;
tags?: string;
unitTestRunner: 'jest' | 'vitest' | 'none';
unitTestRunner?: 'jest' | 'vitest' | 'none';
inSourceTests?: boolean;
/**
* @deprecated
Expand Down Expand Up @@ -41,4 +41,5 @@ export interface NormalizedSchema extends Schema {
fileName: string;
styledModule: null | SupportedStyles;
hasStyles: boolean;
unitTestRunner: 'jest' | 'vitest' | 'none';
}
2 changes: 1 addition & 1 deletion packages/react/src/generators/application/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@
"bundler": {
"description": "The bundler to use.",
"enum": ["vite", "webpack"],
"x-prompt": "Which bundler do you want to use?",
"x-prompt": "Which bundler do you want to use to build the application?",
"default": "webpack"
}
},
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/generators/init/schema.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export interface InitSchema {
unitTestRunner?: 'jest' | 'vitest' | 'none';
e2eTestRunner?: 'cypress' | 'none';
skipBabelConfig?: boolean;
skipFormat?: boolean;
skipPackageJson?: boolean;
js?: boolean;
Expand Down
5 changes: 5 additions & 0 deletions packages/react/src/generators/init/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
"type": "boolean",
"default": false
},
"skipBabelConfig": {
"description": "Do not generate a root babel.config.json (if babel is not needed).",
"type": "boolean",
"default": false
},
"js": {
"type": "boolean",
"default": false,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title><%= className %> Demo</title>
<base href="/" />

<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
</head>
<body>
<div id="root"></div>
<script type="module" src="./src/demo.tsx"></script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* This a a demo file that can be helpful when developing components by serving and interacting with them in the browser.
*/
<% if (component) { %>
import * as ReactDOM from 'react-dom/client';
import { <%= className %> } from './index';

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<<%= className %> />
);
<% } else { %>
import * as ReactDOM from 'react-dom/client';

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<h1><%= className %> Demo</h1>
);
<% } %>
69 changes: 54 additions & 15 deletions packages/react/src/generators/library/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ import {
typesReactRouterDomVersion,
} from '../../utils/versions';
import componentGenerator from '../component/component';
import init from '../init/init';
import initGenerator from '../init/init';
import { Schema } from './schema';
import { updateJestConfigContent } from '../../utils/jest-utils';
import { vitestGenerator } from '@nrwl/vite';
import { viteConfigurationGenerator, vitestGenerator } from '@nrwl/vite';
export interface NormalizedSchema extends Schema {
name: string;
fileName: string;
Expand All @@ -72,10 +72,11 @@ export async function libraryGenerator(host: Tree, schema: Schema) {
options.style = 'none';
}

const initTask = await init(host, {
const initTask = await initGenerator(host, {
...options,
e2eTestRunner: 'none',
skipFormat: true,
skipBabelConfig: options.bundler === 'vite',
});
tasks.push(initTask);

Expand All @@ -90,6 +91,17 @@ export async function libraryGenerator(host: Tree, schema: Schema) {
updateBaseTsConfig(host, options);
}

if (options.buildable && options.bundler === 'vite') {
const viteTask = await viteConfigurationGenerator(host, {
uiFramework: 'react',
project: options.name,
newProject: true,
includeLib: true,
includeVitest: true,
});
tasks.push(viteTask);
}

if (options.unitTestRunner === 'jest') {
const jestTask = await jestProjectGenerator(host, {
...options,
Expand All @@ -110,7 +122,10 @@ export async function libraryGenerator(host: Tree, schema: Schema) {
);
host.write(jestConfigPath, updatedContent);
}
} else if (options.unitTestRunner === 'vitest') {
} else if (
options.unitTestRunner === 'vitest' &&
options.bundler !== 'vite' // tests are already configured if bundler is vite
) {
const vitestTask = await vitestGenerator(host, {
uiFramework: 'react',
project: options.name,
Expand Down Expand Up @@ -299,22 +314,37 @@ function updateBaseTsConfig(host: Tree, options: NormalizedSchema) {
}

function createFiles(host: Tree, options: NormalizedSchema) {
const substitutions = {
...options,
...names(options.name),
tmpl: '',
offsetFromRoot: offsetFromRoot(options.projectRoot),
rootTsConfigPath: getRelativePathToRootTsConfig(host, options.projectRoot),
};

generateFiles(
host,
joinPathFragments(__dirname, './files/lib'),
joinPathFragments(__dirname, './files/common'),
options.projectRoot,
{
...options,
...names(options.name),
tmpl: '',
offsetFromRoot: offsetFromRoot(options.projectRoot),
rootTsConfigPath: getRelativePathToRootTsConfig(
host,
options.projectRoot
),
}
substitutions
);

if (options.bundler === 'vite') {
generateFiles(
host,
joinPathFragments(__dirname, './files/vite'),
options.projectRoot,
substitutions
);
} else if (options.bundler === 'rollup' && options.compiler === 'babel') {
generateFiles(
host,
joinPathFragments(__dirname, './files/rollup-babel'),
options.projectRoot,
substitutions
);
}

if (!options.publishable && !options.buildable) {
host.delete(`${options.projectRoot}/package.json`);
}
Expand Down Expand Up @@ -435,6 +465,9 @@ function normalizeOptions(host: Tree, options: Schema): NormalizedSchema {

const normalized: NormalizedSchema = {
...options,
buildable: options.buildable || options.publishable,
compiler: options.compiler ?? 'babel',
bundler: options.bundler ?? 'rollup',
fileName,
routePath: `/${name}`,
name: projectName,
Expand All @@ -444,6 +477,12 @@ function normalizeOptions(host: Tree, options: Schema): NormalizedSchema {
importPath,
};

// If lib is not buildable then there is no reason to use a bundler or compiler.
if (!normalized.buildable) {
delete normalized.compiler;
delete normalized.bundler;
}

if (options.appProject) {
const appProjectConfig = getProjects(host).get(options.appProject);

Expand Down
1 change: 1 addition & 0 deletions packages/react/src/generators/library/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ export interface Schema {
setParserOptionsProject?: boolean;
standaloneConfig?: boolean;
compiler?: 'babel' | 'swc';
bundler?: 'rollup' | 'vite';
skipPackageJson?: boolean;
}
Loading

0 comments on commit c2a336a

Please sign in to comment.