Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement basic bundleless support #40

Merged
merged 1 commit into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
}
},
"typescript.tsdk": "node_modules/typescript/lib"
}
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ The project is still under development, so it possible dependents on unstable Rs

Current unstable versions are:

<!-- | Package | Version | Link |
| ------------ | ------------------------------------------------------- | --------------------------------------------------------- |
| @rspack/core | @rspack/[email protected] | [PR](https://github.com/webpack/webpack/pull/11751/files) | -->
| Package | Link |
| ------------ | ------------------------------------------------------- |
| @rspack/core | [PR](https://github.com/web-infra-dev/rspack/pull/7210) |
6 changes: 2 additions & 4 deletions e2e/cases/alias/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ export { a };
`;

exports[`source.alias 2`] = `
"(() => { // webpackBootstrap
"use strict";
""use strict";
var __webpack_exports__ = {};

;// CONCATENATED MODULE: ./src/a.ts
Expand All @@ -28,6 +27,5 @@ console.info(a);
var __webpack_export_target__ = exports;
for(var i in __webpack_exports__) __webpack_export_target__[i] = __webpack_exports__[i];
if(__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_target__, '__esModule', { value: true });
})()
;"
"
`;
12 changes: 6 additions & 6 deletions e2e/cases/alias/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { expect, test } from 'vitest';
import { buildAndGetEntryJsResults } from '#shared';
import { buildAndGetJsResults } from '#shared';

test('source.alias', async () => {
const fixturePath = __dirname;
const { contents } = await buildAndGetEntryJsResults(fixturePath);
const { entries } = await buildAndGetJsResults(fixturePath);

expect(contents.esm).toContain('hello world');
expect(contents.cjs).toContain('hello world');
expect(entries.esm).toContain('hello world');
expect(entries.cjs).toContain('hello world');

// simple artifacts check
expect(contents.esm).toMatchSnapshot();
expect(contents.cjs).toMatchSnapshot();
expect(entries.esm).toMatchSnapshot();
expect(entries.cjs).toMatchSnapshot();
});
14 changes: 7 additions & 7 deletions e2e/cases/autoExtension/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { extname, join } from 'node:path';
import { expect, test } from 'vitest';
import { buildAndGetEntryJsResults } from '#shared';
import { buildAndGetJsResults } from '#shared';

test('autoExtension generate .mjs in build artifacts with esm format when type is commonjs', async () => {
const fixturePath = join(__dirname, 'type-commonjs');
const { files } = await buildAndGetEntryJsResults(fixturePath);
expect(extname(files.esm!)).toEqual('.mjs');
expect(extname(files.cjs!)).toEqual('.js');
const { entryFiles } = await buildAndGetJsResults(fixturePath);
expect(extname(entryFiles.esm!)).toEqual('.mjs');
expect(extname(entryFiles.cjs!)).toEqual('.js');
});

test('autoExtension generate .cjs in build artifacts with cjs format when type is module', async () => {
const fixturePath = join(__dirname, 'type-module');
const { files } = await buildAndGetEntryJsResults(fixturePath);
expect(extname(files.esm!)).toEqual('.js');
expect(extname(files.cjs!)).toEqual('.cjs');
const { entryFiles } = await buildAndGetJsResults(fixturePath);
expect(extname(entryFiles.esm!)).toEqual('.js');
expect(extname(entryFiles.cjs!)).toEqual('.cjs');
});
18 changes: 18 additions & 0 deletions e2e/cases/bundle-false/basic/rslib.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { defineConfig } from '@rslib/core';
import { generateBundleCjsConfig, generateBundleEsmConfig } from '#shared';

export default defineConfig({
lib: [
generateBundleEsmConfig(__dirname, {
bundle: false,
}),
generateBundleCjsConfig(__dirname, {
bundle: false,
}),
],
source: {
entry: {
main: ['./src/**'],
},
},
});
3 changes: 3 additions & 0 deletions e2e/cases/bundle-false/basic/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './utils/numbers';
export * from './utils/strings';
export * from './sum';
5 changes: 5 additions & 0 deletions e2e/cases/bundle-false/basic/src/sum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { num1, num2, num3 } from './utils/numbers';
import { str1, str2, str3 } from './utils/strings';

export const numSum = num1 + num2 + num3;
export const strSum = str1 + str2 + str3;
3 changes: 3 additions & 0 deletions e2e/cases/bundle-false/basic/src/utils/numbers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const num1 = 1;
export const num2 = 2;
export const num3 = 3;
3 changes: 3 additions & 0 deletions e2e/cases/bundle-false/basic/src/utils/strings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const str1 = 'str1';
export const str2 = 'str2';
export const str3 = 'str3';
7 changes: 7 additions & 0 deletions e2e/cases/bundle-false/basic/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "@rslib/tsconfig/base",
"compilerOptions": {
"baseUrl": "./"
},
"include": ["src"]
}
13 changes: 13 additions & 0 deletions e2e/cases/bundle-false/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { join } from 'node:path';
import { expect, test } from 'vitest';
import { buildAndGetJsResults } from '#shared';

test('bundle: false', async () => {
const fixturePath = join(__dirname, 'basic');
const { files } = await buildAndGetJsResults(fixturePath);

// TODO: record file paths with inline snapshot
// need to add path serialization
expect(files.esm?.length).toBe(4);
expect(files.cjs?.length).toBe(4);
});
12 changes: 6 additions & 6 deletions e2e/cases/define/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { expect, test } from 'vitest';
import { buildAndGetEntryJsResults } from '#shared';
import { buildAndGetJsResults } from '#shared';

test('source.define', async () => {
const fixturePath = __dirname;
const { contents } = await buildAndGetEntryJsResults(fixturePath);
const { entries } = await buildAndGetJsResults(fixturePath);

expect(contents.esm).not.toContain('console.info(VERSION)');
expect(contents.esm).toContain('1.0.0');
expect(entries.esm).not.toContain('console.info(VERSION)');
expect(entries.esm).toContain('1.0.0');

expect(contents.cjs).not.toContain('console.info(VERSION)');
expect(contents.cjs).toContain('1.0.0');
expect(entries.cjs).not.toContain('console.info(VERSION)');
expect(entries.cjs).toContain('1.0.0');
});
4 changes: 2 additions & 2 deletions e2e/cases/externals/browser/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { join } from 'node:path';
import { expect, test } from 'vitest';
import { buildAndGetEntryJsResults } from '#shared';
import { buildAndGetJsResults } from '#shared';

test('should fail to build when `output.target` is not "node"', async () => {
const fixturePath = join(__dirname);
const build = buildAndGetEntryJsResults(fixturePath);
const build = buildAndGetJsResults(fixturePath);
await expect(build).rejects.toThrowError('Rspack build failed!');
});
8 changes: 4 additions & 4 deletions e2e/cases/externals/node/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import { join } from 'node:path';
import { expect, test } from 'vitest';
import { buildAndGetEntryJsResults } from '#shared';
import { buildAndGetJsResults } from '#shared';

test('auto externalize Node.js built-in modules when `output.target` is "node"', async () => {
const fixturePath = join(__dirname);
const { contents } = await buildAndGetEntryJsResults(fixturePath);
const { entries } = await buildAndGetJsResults(fixturePath);

for (const external of [
'import * as __WEBPACK_EXTERNAL_MODULE_fs__ from "fs"',
'import * as __WEBPACK_EXTERNAL_MODULE_node_assert__ from "node:assert"',
'import * as __WEBPACK_EXTERNAL_MODULE_react__ from "react"',
]) {
expect(contents.esm).toContain(external);
expect(entries.esm).toContain(external);
}

for (const external of [
'var external_fs_namespaceObject = require("fs");',
'var external_node_assert_namespaceObject = require("node:assert");',
'var external_react_namespaceObject = require("react");',
]) {
expect(contents.cjs).toContain(external);
expect(entries.cjs).toContain(external);
}
});
10 changes: 5 additions & 5 deletions e2e/cases/syntax/config/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { expect, test } from 'vitest';
import { buildAndGetEntryJsResults } from '#shared';
import { buildAndGetJsResults } from '#shared';

test('should downgrade class private method by default', async () => {
const fixturePath = __dirname;
const { contents } = await buildAndGetEntryJsResults(fixturePath);
const { entries } = await buildAndGetJsResults(fixturePath);

expect(contents.esm).toMatchSnapshot();
expect(contents.esm).not.toContain('#bar');
expect(entries.esm).toMatchSnapshot();
expect(entries.esm).not.toContain('#bar');

expect(contents.cjs).toContain('#bar');
expect(entries.cjs).toContain('#bar');
});
10 changes: 5 additions & 5 deletions e2e/cases/syntax/default/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { expect, test } from 'vitest';
import { buildAndGetEntryJsResults } from '#shared';
import { buildAndGetJsResults } from '#shared';

test('should downgrade class private method by default', async () => {
const fixturePath = __dirname;
const { contents } = await buildAndGetEntryJsResults(fixturePath);
const { entries } = await buildAndGetJsResults(fixturePath);

expect(contents.esm).toMatchSnapshot();
expect(contents.esm).toContain('#bar');
expect(entries.esm).toMatchSnapshot();
expect(entries.esm).toContain('#bar');

expect(contents.cjs).toContain('#bar');
expect(entries.cjs).toContain('#bar');
});
32 changes: 22 additions & 10 deletions e2e/scripts/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,39 +37,51 @@ export function generateBundleCjsConfig(
return mergeConfig(cjsBasicConfig, config)!;
}

export async function getEntryJsResults(rslibConfig: RslibConfig) {
const files: Record<string, string> = {};
const contents: Record<string, string> = {};
export async function getJsResults(rslibConfig: RslibConfig) {
const files: Record<string, string[]> = {};
const contents: Record<string, Record<string, string>> = {};
const entries: Record<string, string> = {};
const entryFiles: Record<string, string> = {};

for (const libConfig of rslibConfig.lib) {
const result = await globContentJSON(libConfig?.output?.distPath?.root!, {
const content = await globContentJSON(libConfig?.output?.distPath?.root!, {
absolute: true,
ignore: ['/**/*.map'],
});

const entryJs = Object.keys(result).find((file) =>
const jsFiles = Object.keys(content).filter((file) =>
/\.(js|cjs|mjs)$/.test(file),
);

if (entryJs) {
files[libConfig.format!] = entryJs;
contents[libConfig.format!] = result[entryJs]!;
if (jsFiles.length) {
files[libConfig.format!] = jsFiles;
contents[libConfig.format!] = content;
}

// Only applied in bundle mode, a shortcut to get single entry result
if (libConfig.bundle !== false && jsFiles.length === 1) {
entries[libConfig.format!] = Object.values(content)[0]!;
entryFiles[libConfig.format!] = jsFiles[0]!;
}
}

return {
files,
contents,
entries,
entryFiles,
};
}

export const buildAndGetEntryJsResults = async (fixturePath: string) => {
export const buildAndGetJsResults = async (fixturePath: string) => {
const rslibConfig = await loadConfig(join(fixturePath, 'rslib.config.ts'));
process.chdir(fixturePath);
await build(rslibConfig);
const results = await getEntryJsResults(rslibConfig);
const results = await getJsResults(rslibConfig);
return {
contents: results.contents,
files: results.files,
entries: results.entries,
entryFiles: results.entryFiles,
};
};
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@biomejs/biome": "^1.8.3",
"@modern-js/module-tools": "^2.55.0",
"@types/fs-extra": "^11.0.4",
"@types/node": "~18.19.39",
"check-dependency-version-consistency": "^4.1.0",
"cross-env": "^7.0.3",
"cspell-ban-words": "^0.0.3",
Expand All @@ -47,7 +48,7 @@
},
"pnpm": {
"overrides": {
"@rspack/core": "1.0.0-alpha.3"
"@rspack/core": "npm:@rspack/core-canary@1.0.0-canary-d77b591-20240718094414"
}
}
}
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"devDependencies": {
"@rslib/tsconfig": "workspace:*",
"@types/fs-extra": "^11.0.4",
"fast-glob": "^3.3.2",
"commander": "^12.1.0",
"fs-extra": "^11.2.0",
"picocolors": "1.0.1",
Expand Down
1 change: 1 addition & 0 deletions packages/core/prebundle.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default {
},
dependencies: [
'commander',
'fast-glob',
{
name: 'picocolors',
beforeBundle({ depPath }) {
Expand Down
Loading
Loading