Files
test-repo/scripts/build/build-javascript-module.js
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

288 lines
9.3 KiB
JavaScript
Raw Normal View History

import path from "node:path";
2024-06-14 16:34:05 +08:00
import url from "node:url";
import browserslistToEsbuild from "browserslist-to-esbuild";
2022-01-09 01:15:04 +08:00
import esbuild from "esbuild";
import { nodeModulesPolyfillPlugin as esbuildPluginNodeModulePolyfills } from "esbuild-plugins-node-modules-polyfill";
import createEsmUtils from "esm-utils";
import { DIST_DIR, PROJECT_ROOT } from "../utils/index.js";
import esbuildPluginAddDefaultExport from "./esbuild-plugins/add-default-export.js";
2023-03-28 16:18:53 +08:00
import esbuildPluginEvaluate from "./esbuild-plugins/evaluate.js";
import esbuildPluginPrimitiveDefine from "./esbuild-plugins/primitive-define.js";
import esbuildPluginReplaceModule from "./esbuild-plugins/replace-module.js";
import esbuildPluginShimCommonjsObjects from "./esbuild-plugins/shim-commonjs-objects.js";
2023-03-28 16:18:53 +08:00
import esbuildPluginStripNodeProtocol from "./esbuild-plugins/strip-node-protocol.js";
import esbuildPluginThrowWarnings from "./esbuild-plugins/throw-warnings.js";
import esbuildPluginUmd from "./esbuild-plugins/umd.js";
import esbuildPluginVisualizer from "./esbuild-plugins/visualizer.js";
2022-09-18 17:50:14 +08:00
import transform from "./transform/index.js";
import { getPackageFile } from "./utils.js";
2018-05-29 14:59:57 -03:00
2024-06-14 16:34:05 +08:00
const {
dirname,
readJsonSync,
require,
resolve: importMetaResolve,
} = createEsmUtils(import.meta);
2022-02-11 18:02:04 +08:00
const packageJson = readJsonSync("../../package.json");
2020-05-11 09:05:06 +08:00
2022-09-25 11:50:59 +08:00
const universalTarget = browserslistToEsbuild(packageJson.browserslist);
const getRelativePath = (from, to) => {
const relativePath = path.posix.relative(path.dirname(`/${from}`), `/${to}`);
if (!relativePath.startsWith(".")) {
return `./${relativePath}`;
}
return relativePath;
};
2024-07-02 10:01:15 +08:00
function getEsbuildOptions({ file, files, cliOptions }) {
2022-09-25 11:50:59 +08:00
// Save dependencies to file
file.dependencies = [];
const replaceModule = [
2022-02-17 09:47:35 +08:00
// Use `require` directly
2022-03-17 09:44:08 +08:00
{
2022-03-24 15:17:26 +08:00
module: "*",
2022-03-17 09:44:08 +08:00
find: "const require = createRequire(import.meta.url);",
replacement: "",
},
2022-03-17 09:54:48 +08:00
// Use `__dirname` directly
{
2022-03-24 15:17:26 +08:00
module: "*",
2022-03-17 09:54:48 +08:00
find: "const __dirname = path.dirname(fileURLToPath(import.meta.url));",
replacement: "",
},
2024-06-14 16:34:05 +08:00
/*
`jest-docblock` try to detect new line in code, and it will fallback to `os.EOL`,
We already replaced line end to `\n` before calling it
*/
{
module: url.fileURLToPath(importMetaResolve("jest-docblock")),
path: require.resolve("jest-docblock"),
},
{
module: require.resolve("jest-docblock"),
process(text) {
const exports = [
...text.matchAll(
/(?<=\n)exports\.(?<specifier>\w+) = \k<specifier>;/gu,
2024-06-14 16:34:05 +08:00
),
].map((match) => match.groups.specifier);
const lines = text.split("\n");
const startMarkLine = lines.findIndex((line) =>
line.includes("function _interopRequireDefault"),
);
const endMarkLine = lines.indexOf(
"module.exports = __webpack_exports__;",
);
if (
lines[startMarkLine + 1] !== "/**" ||
lines[endMarkLine - 2] !== "})();"
) {
throw new Error("Unexpected source");
}
text = lines.slice(startMarkLine + 1, endMarkLine - 2).join("\n");
text = text
.replace(
"const line = (0, _detectNewline().default)(docblock) ?? _os().EOL;",
String.raw`const line = "\n"`,
)
.replace(
"const line = (0, _detectNewline().default)(comments) ?? _os().EOL;",
String.raw`const line = "\n"`,
);
text += "\n\n" + `export {${exports.join(", ")}};`;
return text;
},
},
// Transform `.at`, `Object.hasOwn`, and `String#replaceAll`
2022-09-18 17:50:14 +08:00
{
module: "*",
process: transform,
},
// #12493, not sure what the problem is, but replace the cjs version with esm version seems fix it
{
module: require.resolve("tslib"),
path: require.resolve("tslib").replace(/tslib\.js$/u, "tslib.es6.js"),
},
2022-05-06 18:52:40 +08:00
// https://github.com/evanw/esbuild/issues/2103
{
module: getPackageFile("outdent/lib-module/index.js"),
2022-05-06 18:52:40 +08:00
process(text) {
const index = text.indexOf('if (typeof module !== "undefined") {');
if (index === -1) {
throw new Error("Unexpected code");
}
return text.slice(0, index);
},
},
2022-03-14 20:02:02 +08:00
];
2022-01-26 19:08:55 +08:00
const define = {
"process.env.PRETTIER_TARGET": file.platform,
"process.env.NODE_ENV": "production",
2022-01-26 19:08:55 +08:00
};
2022-09-25 11:50:59 +08:00
if (file.platform === "universal") {
2018-05-29 14:59:57 -03:00
// We can't reference `process` in UMD bundles and this is
// an undocumented "feature"
replaceModule.push({
module: "*",
2022-03-14 20:02:02 +08:00
find: "process.env.PRETTIER_DEBUG",
replacement: "globalThis.PRETTIER_DEBUG",
});
2022-01-26 19:08:55 +08:00
define.process = undefined;
// @babel/code-frame/lib/index.js
define["process.emitWarning"] = undefined;
// postcss/lib/postcss.js
define["process.env.LANG"] = "";
// @typescript-eslint/typescript-estree
define["process.env.TYPESCRIPT_ESLINT_EXPERIMENTAL_TSSERVER"] = "";
2022-01-26 19:08:55 +08:00
// Replace `__dirname` and `__filename` with a fake value
// So `parser-typescript.js` won't contain a path of working directory
// See #8268
define.__filename = "/prettier-security-filename-placeholder.js";
define.__dirname = "/prettier-security-dirname-placeholder";
2018-05-29 14:59:57 -03:00
}
2020-05-11 09:05:06 +08:00
2022-09-25 11:50:59 +08:00
if (file.platform === "node") {
// External other bundled files
replaceModule.push(
...files
.filter(
(bundle) =>
bundle.input === "package.json" ||
(file.input !== bundle.input && bundle.output.format === "esm"),
)
.map((bundle) => {
let output = bundle.output.file;
if (
file.output.file === "index.cjs" &&
2022-10-13 17:05:20 +08:00
bundle.output.file === "doc.mjs"
2022-09-25 11:50:59 +08:00
) {
output = "doc.js";
}
2022-08-11 14:08:08 +08:00
2022-09-25 11:50:59 +08:00
return {
module: path.join(PROJECT_ROOT, bundle.input),
external: getRelativePath(file.output.file, output),
2022-09-25 11:50:59 +08:00
};
}),
);
} else {
2022-03-24 21:22:41 +08:00
replaceModule.push(
// When running build script with `--no-minify`, `esbuildPluginNodeModulePolyfills` shim `module` module incorrectly
{
module: "*",
find: 'import { createRequire } from "node:module";',
replacement: "",
},
2022-10-04 18:09:24 +08:00
// Prevent `esbuildPluginNodeModulePolyfills` shim `assert`, which will include a big `buffer` shim
// TODO[@fisker]: Find a better way
{
module: "*",
find: ' from "node:assert";',
replacement: ` from ${JSON.stringify(
path.join(dirname, "./shims/assert.js"),
)};`,
},
2022-03-24 21:22:41 +08:00
// Prevent `esbuildPluginNodeModulePolyfills` include shim for this module
{
module: "assert",
path: path.join(dirname, "./shims/assert.js"),
2022-03-24 21:22:41 +08:00
},
// `esbuildPluginNodeModulePolyfills` didn't shim this module
{
module: "module",
text: "export const createRequire = () => {};",
2023-03-24 08:44:25 +08:00
},
// This module requires file access, should not include in universal bundle
{
module: path.join(PROJECT_ROOT, "src/utils/get-interpreter.js"),
text: "export default undefined;",
2022-03-24 21:22:41 +08:00
},
);
}
2022-09-25 11:50:59 +08:00
const { buildOptions } = file;
const shouldMinify =
cliOptions.minify ?? buildOptions.minify ?? file.platform === "universal";
2022-03-14 16:30:12 +08:00
2022-01-09 01:15:04 +08:00
const esbuildOptions = {
2022-09-25 11:50:59 +08:00
entryPoints: [path.join(PROJECT_ROOT, file.input)],
2022-01-09 01:15:04 +08:00
bundle: true,
metafile: true,
plugins: [
esbuildPluginPrimitiveDefine(define),
2022-01-09 01:15:04 +08:00
esbuildPluginEvaluate(),
2022-03-02 13:44:00 +08:00
esbuildPluginStripNodeProtocol(),
esbuildPluginReplaceModule({
2022-09-25 11:50:59 +08:00
replacements: [...replaceModule, ...(buildOptions.replaceModule ?? [])],
2022-01-09 01:15:04 +08:00
}),
2022-09-25 11:50:59 +08:00
file.platform === "universal" && esbuildPluginNodeModulePolyfills(),
cliOptions.reports &&
esbuildPluginVisualizer({ formats: cliOptions.reports }),
2022-06-01 19:23:13 +08:00
esbuildPluginThrowWarnings({
2022-09-25 11:50:59 +08:00
allowDynamicRequire: file.platform === "node",
allowDynamicImport: file.platform === "node",
2022-06-01 19:23:13 +08:00
}),
buildOptions.addDefaultExport && esbuildPluginAddDefaultExport(),
2022-01-09 01:15:04 +08:00
].filter(Boolean),
minify: shouldMinify,
legalComments: "none",
2022-09-25 11:50:59 +08:00
external: ["pnpapi", ...(buildOptions.external ?? [])],
2022-01-09 01:15:04 +08:00
// Disable esbuild auto discover `tsconfig.json` file
tsconfigRaw: JSON.stringify({}),
2022-09-25 11:50:59 +08:00
target: [...(buildOptions.target ?? ["node14"])],
logLevel: "error",
2022-09-25 11:50:59 +08:00
format: file.output.format,
outfile: path.join(DIST_DIR, cliOptions.saveAs ?? file.output.file),
2022-10-20 08:26:35 +08:00
// https://esbuild.github.io/api/#main-fields
mainFields: file.platform === "node" ? ["module", "main"] : undefined,
supported: {
// https://github.com/evanw/esbuild/issues/3471
"regexp-unicode-property-escapes": true,
},
2022-01-09 01:15:04 +08:00
};
2021-09-12 23:26:29 +08:00
2022-09-25 11:50:59 +08:00
if (file.platform === "universal") {
if (!buildOptions.target) {
esbuildOptions.target.push(...universalTarget);
2022-03-13 22:47:02 +08:00
}
2022-01-09 01:15:04 +08:00
2022-09-25 11:50:59 +08:00
if (file.output.format === "umd") {
esbuildOptions.plugins.push(
2022-02-17 09:47:35 +08:00
esbuildPluginUmd({
2022-09-25 11:50:59 +08:00
name: file.output.umdVariableName,
}),
);
}
2022-01-09 01:15:04 +08:00
} else {
2022-02-28 18:38:33 +08:00
esbuildOptions.platform = "node";
2022-09-25 11:50:59 +08:00
esbuildOptions.external.push(...files.map((file) => file.output.file));
2020-10-26 09:44:09 +08:00
2022-08-11 14:08:08 +08:00
// https://github.com/evanw/esbuild/issues/1921
2022-09-25 11:50:59 +08:00
if (file.output.format === "esm") {
2022-08-11 14:08:08 +08:00
esbuildOptions.plugins.push(esbuildPluginShimCommonjsObjects());
}
2020-10-26 09:44:09 +08:00
}
2022-09-25 11:50:59 +08:00
return esbuildOptions;
2018-05-29 14:59:57 -03:00
}
2022-09-25 11:50:59 +08:00
async function runEsbuild(options) {
const esbuildOptions = getEsbuildOptions(options);
2024-07-02 10:01:15 +08:00
return { esbuildResult: await esbuild.build(esbuildOptions) };
2018-05-29 14:59:57 -03:00
}
2022-09-25 11:50:59 +08:00
export default runEsbuild;