From 5ce28ddd7f58f8b4ea6a96e765941ea1ffbb75e5 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Sat, 11 Sep 2021 09:55:46 +0800 Subject: [PATCH] Refactor website build script (#11488) --- netlify.toml | 3 + package.json | 3 +- scripts/build-docs.mjs | 70 ------------- scripts/build-website.mjs | 103 +++++++++++++++++++ scripts/build/build.mjs | 12 +-- scripts/build/bundler.mjs | 2 +- scripts/build/cache.mjs | 7 +- scripts/{build/utils.mjs => utils/index.mjs} | 14 ++- website/README.md | 6 +- yarn.lock | 25 +---- 10 files changed, 137 insertions(+), 108 deletions(-) delete mode 100644 scripts/build-docs.mjs create mode 100644 scripts/build-website.mjs rename scripts/{build/utils.mjs => utils/index.mjs} (76%) diff --git a/netlify.toml b/netlify.toml index ccb7c5f55..15b5c0fbc 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,3 +1,6 @@ +[build] + command = "yarn build:website" + [build.environment] NODE_VERSION = "14" YARN_VERSION = "1.22.10" diff --git a/package.json b/package.json index 80c782171..3eff87a7f 100644 --- a/package.json +++ b/package.json @@ -133,7 +133,6 @@ "rollup": "2.53.3", "rollup-plugin-polyfill-node": "0.7.0", "rollup-plugin-terser": "7.0.2", - "shelljs": "0.8.4", "snapshot-diff": "0.9.0", "tempy": "1.0.1", "terser-webpack-plugin": "5.2.3", @@ -163,7 +162,7 @@ "fix:eslint": "yarn lint:eslint --fix", "fix:prettier": "yarn lint:prettier --write", "build": "node --max-old-space-size=3072 ./scripts/build/build.mjs", - "build-docs": "node ./scripts/build-docs.mjs" + "build:website": "node ./scripts/build-website.mjs" }, "browserslist": [ ">0.5%", diff --git a/scripts/build-docs.mjs b/scripts/build-docs.mjs deleted file mode 100644 index f272159c7..000000000 --- a/scripts/build-docs.mjs +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env node - -import path from "node:path"; -import fs from "node:fs"; -import shell from "shelljs"; -import globby from "globby"; -import prettier from "prettier"; -import createEsmUtils from "esm-utils"; - -shell.config.fatal = true; - -const { __dirname, require } = createEsmUtils(import.meta); -const rootDir = path.join(__dirname, ".."); -const docs = path.join(rootDir, "website/static/lib"); - -function pipe(string) { - return new shell.ShellString(string); -} - -const isPullRequest = process.env.PULL_REQUEST === "true"; -const prettierPath = path.join( - rootDir, - isPullRequest ? "dist" : "node_modules/prettier" -); - -shell.mkdir("-p", docs); - -if (isPullRequest) { - // --- Build prettier for PR --- - const pkg = require("../package.json"); - const newPkg = { ...pkg, version: `999.999.999-pr.${process.env.REVIEW_ID}` }; - pipe(JSON.stringify(newPkg, null, 2)).to("package.json"); - shell.exec("yarn build --playground"); - pipe(JSON.stringify(pkg, null, 2) + "\n").to("package.json"); // restore -} - -shell.cp(`${prettierPath}/standalone.js`, `${docs}/`); -shell.cp(`${prettierPath}/parser-*.js`, `${docs}/`); - -const parserModules = globby.sync(["parser-*.js"], { cwd: prettierPath }); -const parsers = {}; -for (const file of parserModules) { - const plugin = require(path.join(prettierPath, file)); - const property = file.replace(/\.js$/, "").split("-")[1]; - parsers[file] = { - parsers: Object.keys(plugin.parsers), - property, - }; -} - -fs.writeFileSync( - `${docs}/parsers-location.js`, - prettier.format( - ` - "use strict"; - - const parsersLocation = ${JSON.stringify(parsers)}; - `, - { parser: "babel" } - ) -); - -// --- Site --- -shell.cd("website"); -shell.echo("Building website..."); -shell.exec("yarn install"); - -shell.exec("yarn build"); - -shell.echo(); diff --git a/scripts/build-website.mjs b/scripts/build-website.mjs new file mode 100644 index 000000000..8ec0afa6b --- /dev/null +++ b/scripts/build-website.mjs @@ -0,0 +1,103 @@ +#!/usr/bin/env node + +import path from "node:path"; +import fs from "node:fs/promises"; +import globby from "globby"; +import prettier from "prettier"; +import createEsmUtils from "esm-utils"; +import execa from "execa"; +import { + PROJECT_ROOT, + DIST_DIR, + WEBSITE_DIR, + readJson, + writeJson, + copyFile, + writeFile, +} from "./utils/index.mjs"; + +const { require } = createEsmUtils(import.meta); +const runYarn = (command, args, options) => + execa("yarn", [command, ...args], { + stdout: "inherit", + stderr: "inherit", + ...options, + }); +const IS_PULL_REQUEST = process.env.PULL_REQUEST === "true"; +const PRETTIER_DIR = IS_PULL_REQUEST + ? DIST_DIR + : path.dirname(require.resolve("prettier")); +const PLAYGROUND_PRETTIER_DIR = path.join(WEBSITE_DIR, "static/lib"); + +async function buildPrettier() { + // --- Build prettier for PR --- + const packageJsonFile = path.join(PROJECT_ROOT, "package.json"); + const content = await fs.readFile(packageJsonFile); + const packageJson = await readJson(packageJsonFile); + await writeJson(packageJsonFile, { + ...packageJson, + version: `999.999.999-pr.${process.env.REVIEW_ID}`, + }); + + try { + await runYarn("build", ["--playground"], { cwd: PROJECT_ROOT }); + } finally { + // restore + await writeFile(packageJsonFile, content); + } +} + +async function buildPlaygroundFiles() { + const files = await globby(["standalone.js", "parser-*.js"], { + cwd: PRETTIER_DIR, + }); + const parsers = {}; + for (const fileName of files) { + const file = path.join(PRETTIER_DIR, fileName); + await copyFile(file, path.join(PLAYGROUND_PRETTIER_DIR, fileName)); + + if (fileName === "standalone.js") { + continue; + } + + const plugin = require(file); + // We add plugins to the global `prettierPlugins` object + // the name after `parser-` is used as property + // For example to get parsers in `parser-babel.js` via `prettierPlugins.babel` + // See `scripts/build/config.mjs` + const property = fileName.replace(/\.js$/, "").split("-")[1]; + parsers[fileName] = { + property, + parsers: Object.keys(plugin.parsers), + }; + } + + await writeFile( + path.join(PLAYGROUND_PRETTIER_DIR, "parsers-location.js"), + prettier.format( + ` + "use strict"; + + const parsersLocation = ${JSON.stringify(parsers)}; + `, + { parser: "babel" } + ) + ); +} + +(async () => { + if (IS_PULL_REQUEST) { + console.log("Building prettier..."); + await buildPrettier(); + } + + console.log("Preparing files for playground..."); + await buildPlaygroundFiles(); + + // --- Site --- + console.log("Installing website dependencies..."); + await runYarn("install", [], { cwd: WEBSITE_DIR }); + + console.log("Building website..."); + await runYarn("build", [], { cwd: WEBSITE_DIR }); +})(); diff --git a/scripts/build/build.mjs b/scripts/build/build.mjs index 2c718da65..4b61d71b6 100644 --- a/scripts/build/build.mjs +++ b/scripts/build/build.mjs @@ -7,16 +7,16 @@ import chalk from "chalk"; import minimist from "minimist"; import prettyBytes from "pretty-bytes"; import rimraf from "rimraf"; -import bundler from "./bundler.mjs"; -import bundleConfigs from "./config.mjs"; import { PROJECT_ROOT, - CACHE_DIR, + BUILD_CACHE_DIR, DIST_DIR, readJson, writeJson, copyFile, -} from "./utils.mjs"; +} from "../utils/index.mjs"; +import bundler from "./bundler.mjs"; +import bundleConfigs from "./config.mjs"; import Cache from "./cache.mjs"; // Errors in promises should be fatal. @@ -153,13 +153,13 @@ async function run(params) { } if (params["purge-cache"]) { - rimraf.sync(CACHE_DIR); + rimraf.sync(BUILD_CACHE_DIR); } let bundleCache; if (shouldUseCache) { bundleCache = new Cache({ - cacheDir: CACHE_DIR, + cacheDir: BUILD_CACHE_DIR, distDir: DIST_DIR, version: CACHE_VERSION, }); diff --git a/scripts/build/bundler.mjs b/scripts/build/bundler.mjs index 97a1e1a53..b2c556cd5 100644 --- a/scripts/build/bundler.mjs +++ b/scripts/build/bundler.mjs @@ -13,11 +13,11 @@ import { babel as rollupPluginBabel } from "@rollup/plugin-babel"; import WebpackPluginTerser from "terser-webpack-plugin"; import createEsmUtils from "esm-utils"; import builtinModules from "builtin-modules"; +import { PROJECT_ROOT, DIST_DIR } from "../utils/index.mjs"; import rollupPluginExecutable from "./rollup-plugins/executable.mjs"; import rollupPluginEvaluate from "./rollup-plugins/evaluate.mjs"; import rollupPluginReplaceModule from "./rollup-plugins/replace-module.mjs"; import bundles from "./config.mjs"; -import { PROJECT_ROOT, DIST_DIR } from "./utils.mjs"; const { __dirname, require, json } = createEsmUtils(import.meta); const packageJson = json.loadSync("../../package.json"); diff --git a/scripts/build/cache.mjs b/scripts/build/cache.mjs index 3e1a80c31..d3b94fdec 100644 --- a/scripts/build/cache.mjs +++ b/scripts/build/cache.mjs @@ -3,7 +3,12 @@ import crypto from "node:crypto"; import fs from "node:fs/promises"; import path from "node:path"; import { rollup } from "rollup"; -import { PROJECT_ROOT, readJson, writeJson, copyFile } from "./utils.mjs"; +import { + PROJECT_ROOT, + readJson, + writeJson, + copyFile, +} from "../utils/index.mjs"; class Cache { constructor({ cacheDir, distDir, version }) { diff --git a/scripts/build/utils.mjs b/scripts/utils/index.mjs similarity index 76% rename from scripts/build/utils.mjs rename to scripts/utils/index.mjs index 1c4c6d992..3fe0a0e39 100644 --- a/scripts/build/utils.mjs +++ b/scripts/utils/index.mjs @@ -28,7 +28,17 @@ async function writeFile(file, content) { } const PROJECT_ROOT = url.fileURLToPath(new URL("../../", import.meta.url)); -const CACHE_DIR = path.join(PROJECT_ROOT, ".cache"); +const BUILD_CACHE_DIR = path.join(PROJECT_ROOT, ".cache"); const DIST_DIR = path.join(PROJECT_ROOT, "dist"); +const WEBSITE_DIR = path.join(PROJECT_ROOT, "website"); -export { PROJECT_ROOT, DIST_DIR, CACHE_DIR, readJson, writeJson, copyFile }; +export { + PROJECT_ROOT, + DIST_DIR, + BUILD_CACHE_DIR, + WEBSITE_DIR, + readJson, + writeJson, + writeFile, + copyFile, +}; diff --git a/website/README.md b/website/README.md index a410312cb..33a2e507b 100644 --- a/website/README.md +++ b/website/README.md @@ -8,10 +8,10 @@ https://prettier.io/ ```sh cd your/path/to/prettier - yarn build-docs + yarn build:website ``` - To build for the current branch, use `PULL_REQUEST=true yarn build-docs`. Otherwise, a release version of Prettier from `node_modules` is used. + To build for the current branch, use `PULL_REQUEST=true yarn build:website`. Otherwise, a release version of Prettier from `node_modules` is used. 2. Switch to the `website` directory and start the development server: @@ -38,7 +38,7 @@ Images and other static assets are placed inside the `static` directory: `static The Playground is not integrated with the Docusaurus infrastructure. Its UI (`website/playground/`) is built separately with webpack configured to put the resulting bundle in Docusaurus’s `static` directory. The `yarn start` command (in `website/`) concurrently starts both Docusaurus’s local server and webpack in the watch mode for the Playground. -Another part of the Playground is a web worker where formatting happens. It’s not managed by webpack and resides directly in `static/worker.js`. It expects to find the [UMD bundles of Prettier](https://prettier.io/docs/en/browser.html) in `static/lib/`. That’s why running `yarn build-docs` or `PULL_REQUEST=true yarn build-docs` in the project root is a required step. +Another part of the Playground is a web worker where formatting happens. It’s not managed by webpack and resides directly in `static/worker.js`. It expects to find the [UMD bundles of Prettier](https://prettier.io/docs/en/browser.html) in `static/lib/`. That’s why running `yarn build:website` or `PULL_REQUEST=true yarn build:website` in the project root is a required step. Finally, there is a service worker that caches Prettier’s relatively heavy bundles (`static/service-worker.js`). diff --git a/yarn.lock b/yarn.lock index f37ad4782..640958707 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3439,7 +3439,7 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7: +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7: version "7.1.7" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== @@ -3679,11 +3679,6 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" -interpret@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - is-alphabetical@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" @@ -5366,13 +5361,6 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= - dependencies: - resolve "^1.1.6" - refa@^0.9.0: version "0.9.1" resolved "https://registry.yarnpkg.com/refa/-/refa-0.9.1.tgz#12731fce378d235731b1f73182b20083c8a75ca8" @@ -5532,7 +5520,7 @@ resolve-global@^1.0.0: dependencies: global-dirs "^0.1.1" -resolve@1.20.0, resolve@^1.1.6, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.20.0: +resolve@1.20.0, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.20.0: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -5717,15 +5705,6 @@ shell-quote@^1.6.1: resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== -shelljs@0.8.4: - version "0.8.4" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" - integrity sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ== - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"