Files
test-repo/scripts/build/bundler.mjs
T

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

381 lines
10 KiB
JavaScript
Raw Normal View History

2021-05-15 20:09:52 +08:00
import path from "node:path";
import fs from "node:fs";
import { rollup } from "rollup";
import webpack from "webpack";
import { nodeResolve as rollupPluginNodeResolve } from "@rollup/plugin-node-resolve";
import rollupPluginAlias from "@rollup/plugin-alias";
import rollupPluginCommonjs from "@rollup/plugin-commonjs";
import rollupPluginPolyfillNode from "rollup-plugin-polyfill-node";
import rollupPluginJson from "@rollup/plugin-json";
import rollupPluginReplace from "@rollup/plugin-replace";
import { terser as rollupPluginTerser } from "rollup-plugin-terser";
import { babel as rollupPluginBabel } from "@rollup/plugin-babel";
import WebpackPluginTerser from "terser-webpack-plugin";
import createEsmUtils from "esm-utils";
import rollupPluginExecutable from "./rollup-plugins/executable.mjs";
import rollupPluginEvaluate from "./rollup-plugins/evaluate.mjs";
import rollupPluginExternals from "./rollup-plugins/externals.mjs";
2018-05-29 14:59:57 -03:00
2021-05-15 20:09:52 +08:00
const { __dirname, require } = createEsmUtils(import.meta);
const PROJECT_ROOT = path.join(__dirname, "../..");
2020-05-11 09:05:06 +08:00
2018-05-29 14:59:57 -03:00
const EXTERNALS = [
"assert",
"buffer",
"constants",
"crypto",
"events",
"fs",
"module",
"os",
"path",
"stream",
"url",
"util",
"readline",
2020-01-22 21:36:07 +08:00
"tty",
2018-05-29 14:59:57 -03:00
];
2020-05-11 09:05:06 +08:00
const entries = [
// Force using the CJS file, instead of ESM; i.e. get the file
// from `"main"` instead of `"module"` (rollup default) of package.json
{
find: "outdent",
replacement: require.resolve("outdent"),
},
{
find: "lines-and-columns",
replacement: require.resolve("lines-and-columns"),
},
{
find: "@angular/compiler/src",
replacement: path.resolve(
`${PROJECT_ROOT}/node_modules/@angular/compiler/esm2015/src`
),
},
2020-12-02 11:10:53 +08:00
// Avoid rollup `SOURCEMAP_ERROR` and `THIS_IS_UNDEFINED` error
{
find: "@glimmer/syntax",
replacement: require.resolve("@glimmer/syntax"),
},
2020-05-11 09:05:06 +08:00
];
function webpackNativeShims(config, modules) {
if (!config.resolve) {
config.resolve = {};
}
const { resolve } = config;
resolve.alias = resolve.alias || {};
resolve.fallback = resolve.fallback || {};
for (const module of modules) {
if (module in resolve.alias || module in resolve.fallback) {
throw new Error(`fallback/alias for "${module}" already exists.`);
}
const file = path.join(__dirname, `shims/${module}.mjs`);
if (fs.existsSync(file)) {
resolve.alias[module] = file;
} else {
resolve.fallback[module] = false;
}
}
return config;
}
2018-05-29 14:59:57 -03:00
function getBabelConfig(bundle) {
const config = {
babelrc: false,
2021-05-12 08:11:43 +08:00
assumptions: {
setSpreadProperties: true,
},
sourceType: "unambiguous",
2018-06-21 10:29:42 +08:00
plugins: bundle.babelPlugins || [],
2018-05-29 14:59:57 -03:00
compact: bundle.type === "plugin" ? false : "auto",
exclude: [/\/core-js\//],
2018-05-29 14:59:57 -03:00
};
if (bundle.type === "core") {
config.plugins.push(
require.resolve("./babel-plugins/transform-custom-require")
);
}
const targets = { node: "10" };
2018-05-29 14:59:57 -03:00
if (bundle.target === "universal") {
2020-01-29 08:03:36 +08:00
targets.browsers = [
">0.5%",
"not ie 11",
"not safari 5.1",
"not op_mini all",
];
2018-05-29 14:59:57 -03:00
}
config.presets = [
2020-01-10 09:21:44 +08:00
[
2021-05-12 08:11:43 +08:00
"@babel/preset-env",
2020-01-10 09:21:44 +08:00
{
targets,
exclude: [
"es.array.unscopables.flat-map",
"es.promise",
"es.promise.finally",
"es.string.replace",
"es.symbol.description",
"es.typed-array.*",
"web.*",
],
2020-01-10 09:21:44 +08:00
modules: false,
useBuiltIns: "usage",
corejs: {
version: 3,
},
debug: false,
2020-01-10 09:21:44 +08:00
},
],
2018-05-29 14:59:57 -03:00
];
2021-05-12 08:11:43 +08:00
config.plugins.push([
"@babel/plugin-proposal-object-rest-spread",
{ useBuiltIns: true },
]);
2018-05-29 14:59:57 -03:00
return config;
}
function getRollupConfig(bundle) {
const config = {
2019-06-08 03:58:05 +08:00
input: bundle.input,
2018-05-29 14:59:57 -03:00
onwarn(warning) {
if (
// We use `eval("require")` to enable dynamic requires in the
// custom parser API
warning.code === "EVAL" ||
2019-06-08 03:58:05 +08:00
// ignore `MIXED_EXPORTS` warn
warning.code === "MIXED_EXPORTS" ||
2018-05-29 14:59:57 -03:00
(warning.code === "CIRCULAR_DEPENDENCY" &&
(warning.importer.startsWith("node_modules") ||
2021-03-08 23:08:47 +08:00
warning.importer.startsWith("\x00polyfill-node:"))) ||
warning.code === "SOURCEMAP_ERROR" ||
warning.code === "THIS_IS_UNDEFINED"
2018-05-29 14:59:57 -03:00
) {
return;
}
// web bundle can't have external requires
if (
warning.code === "UNRESOLVED_IMPORT" &&
bundle.target === "universal"
) {
throw new Error(
`Unresolved dependency in universal bundle: ${warning.source}`
);
}
console.warn(warning);
},
};
const replaceStrings = {
"process.env.PRETTIER_TARGET": JSON.stringify(bundle.target),
"process.env.NODE_ENV": JSON.stringify("production"),
2018-05-29 14:59:57 -03:00
};
if (bundle.target === "universal") {
// We can't reference `process` in UMD bundles and this is
// an undocumented "feature"
replaceStrings["process.env.PRETTIER_DEBUG"] = "global.PRETTIER_DEBUG";
// `rollup-plugin-node-globals` replace `__dirname` with the real dirname
// `parser-typescript.js` will contain a path of working directory
// See #8268
replaceStrings.__filename = JSON.stringify(
"/prettier-security-filename-placeholder.js"
);
replaceStrings.__dirname = JSON.stringify(
"/prettier-security-dirname-placeholder"
);
2018-05-29 14:59:57 -03:00
}
Object.assign(replaceStrings, bundle.replace);
const babelConfig = { babelHelpers: "bundled", ...getBabelConfig(bundle) };
2018-05-29 14:59:57 -03:00
2020-05-11 09:05:06 +08:00
const alias = { ...bundle.alias };
alias.entries = [...entries, ...(alias.entries || [])];
2018-05-29 14:59:57 -03:00
config.plugins = [
2021-05-15 20:09:52 +08:00
rollupPluginReplace({
2019-06-08 03:58:05 +08:00
values: replaceStrings,
delimiters: ["", ""],
2021-03-08 23:08:47 +08:00
preventAssignment: true,
2019-06-08 03:58:05 +08:00
}),
2021-05-15 20:09:52 +08:00
rollupPluginExecutable(),
rollupPluginEvaluate(),
rollupPluginJson(),
2020-05-11 09:05:06 +08:00
rollupPluginAlias(alias),
2021-05-15 20:09:52 +08:00
rollupPluginNodeResolve({
2018-05-29 14:59:57 -03:00
extensions: [".js", ".json"],
preferBuiltins: bundle.target === "node",
}),
2021-05-15 20:09:52 +08:00
rollupPluginCommonjs({
2020-01-31 08:13:37 +08:00
ignoreGlobal: bundle.target === "node",
...bundle.commonjs,
2020-08-24 18:19:13 +08:00
ignore:
bundle.type === "plugin"
? undefined
: (id) => /\.\/parser-.*?/.test(id),
requireReturnsDefault: "preferred",
2020-01-31 08:13:37 +08:00
}),
2021-05-15 20:09:52 +08:00
rollupPluginExternals(bundle.externals),
bundle.target === "universal" && rollupPluginPolyfillNode(),
2021-05-15 20:09:52 +08:00
rollupPluginBabel(babelConfig),
2020-09-17 01:08:44 +09:00
bundle.minify !== false &&
bundle.target === "universal" &&
2021-05-15 20:09:52 +08:00
rollupPluginTerser({
2020-09-17 01:08:44 +09:00
output: {
ascii_only: true,
},
}),
2018-05-29 14:59:57 -03:00
].filter(Boolean);
if (bundle.target === "node") {
2019-06-07 18:20:40 -03:00
config.external = EXTERNALS;
2018-05-29 14:59:57 -03:00
}
return config;
}
2020-10-26 09:44:09 +08:00
function getRollupOutputOptions(bundle, buildOptions) {
2018-05-29 14:59:57 -03:00
const options = {
// Avoid warning form #8797
exports: "auto",
2019-06-08 03:58:05 +08:00
file: `dist/${bundle.output}`,
2018-05-29 14:59:57 -03:00
};
2019-06-08 03:58:05 +08:00
2018-05-29 14:59:57 -03:00
if (bundle.target === "node") {
options.format = "cjs";
} else if (bundle.target === "universal") {
2019-06-08 03:58:05 +08:00
options.name =
2018-05-29 14:59:57 -03:00
bundle.type === "plugin" ? `prettierPlugins.${bundle.name}` : bundle.name;
2020-09-17 01:08:44 +09:00
if (!bundle.format && bundle.bundler !== "webpack") {
return [
{
...options,
format: "umd",
},
2020-10-26 09:44:09 +08:00
!buildOptions.playground && {
2020-09-17 01:08:44 +09:00
...options,
format: "esm",
file: `dist/esm/${bundle.output.replace(".js", ".mjs")}`,
},
2020-10-26 09:44:09 +08:00
].filter(Boolean);
2020-09-17 01:08:44 +09:00
}
options.format = bundle.format;
2018-05-29 14:59:57 -03:00
}
2020-10-26 09:44:09 +08:00
if (buildOptions.playground && bundle.bundler !== "webpack") {
return { skipped: true };
}
2020-09-17 01:08:44 +09:00
return [options];
2018-05-29 14:59:57 -03:00
}
function getWebpackConfig(bundle) {
2018-06-13 17:23:33 -03:00
if (bundle.type !== "plugin" || bundle.target !== "universal") {
throw new Error("Must use rollup for this bundle");
2018-05-29 14:59:57 -03:00
}
const root = path.resolve(__dirname, "..", "..");
2019-09-16 17:13:32 +08:00
const config = {
mode: "production",
performance: { hints: false },
2018-05-29 14:59:57 -03:00
entry: path.resolve(root, bundle.input),
2018-06-13 17:23:33 -03:00
module: {
rules: [
{
test: /\.js$/,
use: {
loader: "babel-loader",
options: getBabelConfig(bundle),
},
},
],
},
2018-05-29 14:59:57 -03:00
output: {
path: path.resolve(root, "dist"),
filename: bundle.output,
library: {
type: "umd",
name: ["prettierPlugins", bundle.name],
},
2019-09-14 05:55:30 +08:00
// https://github.com/webpack/webpack/issues/6642
globalObject: 'new Function("return this")()',
},
optimization: {},
resolve: {
// Webpack@5 can't resolve "postcss/lib/parser" and "postcss/lib/stringifier"" imported by `postcss-scss`
// Ignore `exports` field to fix bundle script
exportsFields: [],
},
2018-05-29 14:59:57 -03:00
};
2019-09-16 17:13:32 +08:00
if (bundle.terserOptions) {
2021-05-15 20:09:52 +08:00
config.optimization.minimizer = [
new WebpackPluginTerser(bundle.terserOptions),
];
2019-09-16 17:13:32 +08:00
}
// config.optimization.minimize = false;
2019-09-16 17:13:32 +08:00
return webpackNativeShims(config, ["os", "path", "util", "url", "fs"]);
2018-05-29 14:59:57 -03:00
}
function runWebpack(config) {
return new Promise((resolve, reject) => {
webpack(config, (error, stats) => {
if (error) {
reject(error);
return;
2018-05-29 14:59:57 -03:00
}
if (stats.hasErrors()) {
const { errors } = stats.toJson();
const error = new Error(errors[0].message);
error.errors = errors;
reject(error);
return;
}
if (stats.hasWarnings()) {
const { warnings } = stats.toJson();
console.warn(warnings);
}
resolve();
2018-05-29 14:59:57 -03:00
});
});
}
2021-05-15 20:09:52 +08:00
async function createBundle(bundle, cache, options) {
2019-06-08 03:58:05 +08:00
const inputOptions = getRollupConfig(bundle);
2020-10-26 09:44:09 +08:00
const outputOptions = getRollupOutputOptions(bundle, options);
if (!Array.isArray(outputOptions) && outputOptions.skipped) {
return { skipped: true };
}
2019-06-08 03:58:05 +08:00
if (
!options["purge-cache"] &&
(
await Promise.all(
outputOptions.map((outputOption) =>
2021-01-11 13:25:34 +09:00
cache.isCached(inputOptions, outputOption)
)
)
).every((cached) => cached)
) {
2020-09-17 01:08:44 +09:00
return { cached: true };
2018-06-18 15:16:40 -03:00
}
2018-05-29 14:59:57 -03:00
if (bundle.bundler === "webpack") {
await runWebpack(getWebpackConfig(bundle));
} else {
2019-06-08 03:58:05 +08:00
const result = await rollup(inputOptions);
2020-09-17 01:08:44 +09:00
await Promise.all(outputOptions.map((option) => result.write(option)));
2018-05-29 14:59:57 -03:00
}
2018-06-18 15:16:40 -03:00
return { bundled: true };
2021-05-15 20:09:52 +08:00
}
export default createBundle;