Commit 1568ca9

Anton Golub <antongolub@antongolub.com>
2024-05-05 17:49:14
build: refactor build:js script (#794)
* chore: update esbuild plugins, yaml to 2.42, ts to 5.4.5 * build: refactor build:js script * style: fix import `url → node:url`
1 parent 086b500
scripts/build-js.mjs
@@ -15,7 +15,9 @@
 // limitations under the License.
 
 import path from 'node:path'
+import fs from 'node:fs'
 import esbuild from 'esbuild'
+import { parseContentsLayout } from 'esbuild-plugin-utils'
 import { nodeExternalsPlugin } from 'esbuild-node-externals'
 import { entryChunksPlugin } from 'esbuild-plugin-entry-chunks'
 import { hybridExportPlugin } from 'esbuild-plugin-hybrid-export'
@@ -36,7 +38,7 @@ const argv = minimist(process.argv.slice(2), {
     target: 'node12',
     cwd: process.cwd(),
   },
-  boolean: ['minify', 'sourcemap', 'banner', 'hybrid'],
+  boolean: ['minify', 'sourcemap', 'hybrid'],
   string: ['entry', 'external', 'bundle', 'license', 'format', 'map', 'cwd'],
 })
 const {
@@ -51,6 +53,7 @@ const {
   cwd: _cwd,
 } = argv
 
+const formats = format.split(',')
 const plugins = []
 const cwd = Array.isArray(_cwd) ? _cwd[_cwd.length - 1] : _cwd
 const entries = entry.split(/,\s?/)
@@ -86,14 +89,33 @@ plugins.push(
     hooks: [
       {
         on: 'end',
-        pattern: new RegExp(
-          '(' +
-            entryPoints.map((e) => path.parse(e).name).join('|') +
-            ')\\.cjs$'
-        ),
+        pattern: entryPointsToRegexp(entryPoints),
+        transform(contents, p) {
+          const { header, body } = parseContentsLayout(contents)
+          return [
+            header,
+            // https://github.com/evanw/esbuild/issues/1633
+            body.includes('import_meta')
+              ? inject('./scripts/import-meta-url.polyfill.js')
+              : '',
+
+            //https://github.com/evanw/esbuild/issues/1921
+            // p.includes('vendor') ? inject('./scripts/require.polyfill.js') : '',
+
+            body,
+          ]
+            .filter(Boolean)
+            .join('\n')
+        },
+      },
+      {
+        on: 'end',
+        pattern: entryPointsToRegexp(entryPoints),
         transform(contents) {
           return contents
             .toString()
+            .replaceAll('import.meta.url', 'import_meta_url')
+            .replaceAll('import_meta.url', 'import_meta_url')
             .replaceAll('"node:', '"')
             .replaceAll(
               'require("stream/promises")',
@@ -115,17 +137,18 @@ plugins.push(
   })
 )
 
-const formats = format.split(',')
-const banner =
-  argv.banner && bundle === 'all'
-    ? {
-        js: `
-const require = (await import("node:module")).createRequire(import.meta.url);
-const __filename = (await import("node:url")).fileURLToPath(import.meta.url);
-const __dirname = (await import("node:path")).dirname(__filename);
-`,
-      }
-    : {}
+function inject(file) {
+  const extra = fs.readFileSync(file, 'utf8')
+  return `// ${file}
+${extra}
+`
+}
+
+function entryPointsToRegexp(entryPoints) {
+  return new RegExp(
+    '(' + entryPoints.map((e) => path.parse(e).name).join('|') + ')\\.cjs$'
+  )
+}
 
 const esmConfig = {
   absWorkingDir: cwd,
@@ -145,8 +168,6 @@ const esmConfig = {
   plugins,
   legalComments: license,
   tsconfig: './tsconfig.json',
-  //https://github.com/evanw/esbuild/issues/1921
-  banner,
 }
 
 const cjsConfig = {
@@ -154,20 +175,14 @@ const cjsConfig = {
   outdir: './build',
   target: 'es6',
   format: 'cjs',
-  banner: {},
   outExtension: {
     '.js': '.cjs',
   },
-  // https://github.com/evanw/esbuild/issues/1633
-  define: {
-    'import.meta.url': 'import_meta_url',
-  },
-  inject: ['./scripts/import.meta.url-polyfill.js'],
 }
 
 for (const format of formats) {
   const config = format === 'cjs' ? cjsConfig : esmConfig
-  console.log('config=', config)
+  console.log('esbuild config:', config)
 
   await esbuild.build(config).catch(() => process.exit(1))
 }
scripts/import.meta.url-polyfill.js → scripts/import-meta-url.polyfill.js
@@ -1,4 +1,4 @@
-export const import_meta_url =
+const import_meta_url =
   typeof document === 'undefined'
     ? new (require('url'.replace('', '')).URL)('file:' + __filename).href
     : (document.currentScript && document.currentScript.src) ||
scripts/require.polyfill.js
@@ -0,0 +1,3 @@
+const require = (await import('node:module')).createRequire(import.meta.url)
+const __filename = (await import('node:url')).fileURLToPath(import.meta.url)
+const __dirname = (await import('node:path')).dirname(__filename)
src/vendor.ts
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+import { URL } from 'node:url'
 import {
   convertPathToPattern,
   globby,
@@ -24,7 +25,6 @@ import {
   isDynamicPattern,
   type Options as GlobbyOptions,
 } from 'globby'
-
 import * as yaml from 'yaml'
 import * as _fs from 'fs-extra'
 import type { fetch } from 'node-fetch-native'
@@ -33,7 +33,6 @@ import { AbortController } from 'node-abort-controller'
 export { exec, buildCmd } from 'zurk/spawn'
 
 import _createRequire from 'create-require'
-import { URL } from 'url'
 
 export const createRequire = _createRequire as unknown as (
   filename: string | URL
test/fixtures/js-project/package-lock.json
@@ -28,10 +28,11 @@
         "dts-bundle-generator": "^9.5.1",
         "esbuild": "^0.20.2",
         "esbuild-node-externals": "^1.13.0",
-        "esbuild-plugin-entry-chunks": "^0.1.12",
-        "esbuild-plugin-extract-helpers": "^0.0.3",
-        "esbuild-plugin-hybrid-export": "^0.2.1",
-        "esbuild-plugin-transform-hook": "^0.0.1",
+        "esbuild-plugin-entry-chunks": "^0.1.14",
+        "esbuild-plugin-extract-helpers": "^0.0.5",
+        "esbuild-plugin-hybrid-export": "^0.2.3",
+        "esbuild-plugin-transform-hook": "^0.0.3",
+        "esbuild-plugin-utils": "^0.0.1",
         "fs-extra": "^11.2.0",
         "fx": "*",
         "globby": "^14.0.1",
@@ -41,9 +42,9 @@
         "node-fetch-native": "^1.6.4",
         "prettier": "^3.2.5",
         "tsd": "^0.31.0",
-        "typescript": "^5.4.4",
+        "typescript": "^5.4.5",
         "which": "^4.0.0",
-        "yaml": "^2.4.1",
+        "yaml": "^2.4.2",
         "zurk": "^0.1.4"
       },
       "engines": {
@@ -51,7 +52,7 @@
       },
       "optionalDependencies": {
         "@types/fs-extra": "^11.0.4",
-        "@types/node": ">=20.12.5"
+        "@types/node": ">=20.12.8"
       }
     },
     "node_modules/zx": {
test/extra.test.js
@@ -19,7 +19,7 @@ import { globby } from '../build/index.js'
 
 describe('extra', () => {
   test('every file should have a license', async () => {
-    const files = await globby(['**/*.{js,mjs,ts}', '!**/*-polyfill.js'], {
+    const files = await globby(['**/*.{js,mjs,ts}', '!**/*polyfill.js'], {
       gitignore: true,
       onlyFiles: true,
       cwd: process.cwd(),
package-lock.json
@@ -25,10 +25,11 @@
         "dts-bundle-generator": "^9.5.1",
         "esbuild": "^0.20.2",
         "esbuild-node-externals": "^1.13.0",
-        "esbuild-plugin-entry-chunks": "^0.1.12",
-        "esbuild-plugin-extract-helpers": "^0.0.3",
-        "esbuild-plugin-hybrid-export": "^0.2.1",
-        "esbuild-plugin-transform-hook": "^0.0.1",
+        "esbuild-plugin-entry-chunks": "^0.1.14",
+        "esbuild-plugin-extract-helpers": "^0.0.5",
+        "esbuild-plugin-hybrid-export": "^0.2.3",
+        "esbuild-plugin-transform-hook": "^0.0.3",
+        "esbuild-plugin-utils": "^0.0.1",
         "fs-extra": "^11.2.0",
         "fx": "*",
         "globby": "^14.0.1",
@@ -38,9 +39,9 @@
         "node-fetch-native": "^1.6.4",
         "prettier": "^3.2.5",
         "tsd": "^0.31.0",
-        "typescript": "^5.4.4",
+        "typescript": "^5.4.5",
         "which": "^4.0.0",
-        "yaml": "^2.4.1",
+        "yaml": "^2.4.2",
         "zurk": "^0.1.4"
       },
       "engines": {
@@ -48,7 +49,7 @@
       },
       "optionalDependencies": {
         "@types/fs-extra": "^11.0.4",
-        "@types/node": ">=20.12.5"
+        "@types/node": ">=20.12.8"
       }
     },
     "node_modules/@babel/code-frame": {
@@ -1302,42 +1303,58 @@
       }
     },
     "node_modules/esbuild-plugin-entry-chunks": {
-      "version": "0.1.12",
-      "resolved": "https://registry.npmjs.org/esbuild-plugin-entry-chunks/-/esbuild-plugin-entry-chunks-0.1.12.tgz",
-      "integrity": "sha512-lFcfXObH5F5hgtYAK0EgyuVLk7QJI9NPjBXSo+Un+sCvd3oytchCyV9mHx6kh1rnOzLHNPbPjyTt9pNAfF7tHA==",
+      "version": "0.1.14",
+      "resolved": "https://registry.npmjs.org/esbuild-plugin-entry-chunks/-/esbuild-plugin-entry-chunks-0.1.14.tgz",
+      "integrity": "sha512-qKX5U0xZugLlU3wWQQRmbxYAWc+YUAGQnkVHjSeFcaK6WsZ/pTPAjcowdGs99JMOq5El6bupOSzm8v3dLFx4Hw==",
       "dev": true,
       "dependencies": {
-        "depseek": "0.4.1"
+        "depseek": "0.4.1",
+        "esbuild-plugin-utils": "0.0.1"
       },
       "peerDependencies": {
         "esbuild": ">=0.19.0"
       }
     },
     "node_modules/esbuild-plugin-extract-helpers": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/esbuild-plugin-extract-helpers/-/esbuild-plugin-extract-helpers-0.0.3.tgz",
-      "integrity": "sha512-pD9p+WHsrN8iyRRFuI8on1grE0KQhiOmueYQV/PLHWzydY1fliNfydiRl5yemE+0S7keJ/ga2F9SCLUzS4H4tw==",
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/esbuild-plugin-extract-helpers/-/esbuild-plugin-extract-helpers-0.0.5.tgz",
+      "integrity": "sha512-kzTvoEpd+P3fgJWS4TiVTWSirONwIYYk4iMp7UeBYJzD4ncGvlRmDTlwrbX5ZwP0uP/IxkjNJp8X7TJHK5dQvQ==",
       "dev": true,
       "dependencies": {
-        "esbuild-plugin-transform-hook": "0.0.1"
+        "esbuild-plugin-utils": "0.0.1"
       },
       "peerDependencies": {
         "esbuild": ">=0.19.0"
       }
     },
     "node_modules/esbuild-plugin-hybrid-export": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/esbuild-plugin-hybrid-export/-/esbuild-plugin-hybrid-export-0.2.1.tgz",
-      "integrity": "sha512-vdFLmsekj+lDihz7LAr61ApDsEQtVdUvwlGc+asnBlZbSG5DtCSlBkFR0FlJ+L4fjsQ62Supo3tAEd7K/oq48w==",
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/esbuild-plugin-hybrid-export/-/esbuild-plugin-hybrid-export-0.2.3.tgz",
+      "integrity": "sha512-cs1bTHqbgcdxoMM+66m7yd4USXnWClPFzq4HJN3vByLI5GJm7vmjuF7i/vV3D+KOUuYSCb6BxA8t7ltCTqR/QA==",
       "dev": true,
+      "dependencies": {
+        "esbuild-plugin-utils": "0.0.1"
+      },
       "peerDependencies": {
         "esbuild": ">=0.19.0"
       }
     },
     "node_modules/esbuild-plugin-transform-hook": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/esbuild-plugin-transform-hook/-/esbuild-plugin-transform-hook-0.0.3.tgz",
+      "integrity": "sha512-TG247XIX0SWTqQKxI60rQl7NR4FaD0852kVYObzJSI+uH0Xnin8rpR23xZf7cCeOrb/U3pq7rhxuTCwzvGSssA==",
+      "dev": true,
+      "dependencies": {
+        "esbuild-plugin-utils": "0.0.1"
+      },
+      "peerDependencies": {
+        "esbuild": ">=0.19.0"
+      }
+    },
+    "node_modules/esbuild-plugin-utils": {
       "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/esbuild-plugin-transform-hook/-/esbuild-plugin-transform-hook-0.0.1.tgz",
-      "integrity": "sha512-OurhRFH6FYJcMKEw73/aAyOTSH+weEoHNuAuRnITR13u6BnSeXbuVdMS+Zuq1Mc/oGuk9hFIjm6MMsHNb+42kw==",
+      "resolved": "https://registry.npmjs.org/esbuild-plugin-utils/-/esbuild-plugin-utils-0.0.1.tgz",
+      "integrity": "sha512-LKdHss3Sdc+yu3tYIKb67Xvrub3AwQu+qdvmEFJWeSbTd6ulbiQxZavSkiSwwYXmLyg6Sdgc2inoaG743R+0cQ==",
       "dev": true,
       "peerDependencies": {
         "esbuild": ">=0.19.0"
@@ -4182,9 +4199,9 @@
       }
     },
     "node_modules/typescript": {
-      "version": "5.4.4",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz",
-      "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==",
+      "version": "5.4.5",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
+      "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
       "dev": true,
       "bin": {
         "tsc": "bin/tsc",
@@ -4330,9 +4347,9 @@
       "dev": true
     },
     "node_modules/yaml": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz",
-      "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==",
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz",
+      "integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==",
       "dev": true,
       "bin": {
         "yaml": "bin.mjs"
package.json
@@ -76,7 +76,7 @@
   },
   "optionalDependencies": {
     "@types/fs-extra": "^11.0.4",
-    "@types/node": ">=20.12.5"
+    "@types/node": ">=20.12.8"
   },
   "devDependencies": {
     "@types/fs-extra": "^11.0.4",
@@ -92,10 +92,11 @@
     "dts-bundle-generator": "^9.5.1",
     "esbuild": "^0.20.2",
     "esbuild-node-externals": "^1.13.0",
-    "esbuild-plugin-entry-chunks": "^0.1.12",
-    "esbuild-plugin-hybrid-export": "^0.2.1",
-    "esbuild-plugin-transform-hook": "^0.0.1",
-    "esbuild-plugin-extract-helpers": "^0.0.3",
+    "esbuild-plugin-utils": "^0.0.1",
+    "esbuild-plugin-entry-chunks": "^0.1.14",
+    "esbuild-plugin-hybrid-export": "^0.2.3",
+    "esbuild-plugin-transform-hook": "^0.0.3",
+    "esbuild-plugin-extract-helpers": "^0.0.5",
     "fs-extra": "^11.2.0",
     "fx": "*",
     "globby": "^14.0.1",
@@ -105,9 +106,9 @@
     "node-fetch-native": "^1.6.4",
     "prettier": "^3.2.5",
     "tsd": "^0.31.0",
-    "typescript": "^5.4.4",
+    "typescript": "^5.4.5",
     "which": "^4.0.0",
-    "yaml": "^2.4.1",
+    "yaml": "^2.4.2",
     "zurk": "^0.1.4"
   },
   "publishConfig": {