Browse Source

refactor(build): enhance dev script with dynamic target handling and polyfills (#14376)

edison 2 tháng trước cách đây
mục cha
commit
4ba2ad5813
2 tập tin đã thay đổi với 144 bổ sung22 xóa
  1. 137 22
      scripts/dev.js
  2. 7 0
      scripts/shim-fs.js

+ 137 - 22
scripts/dev.js

@@ -1,8 +1,16 @@
 // @ts-check
 
-import { watch } from 'rolldown'
-import { createConfigsForPackage } from './create-rolldown-config.js'
+import fs from 'node:fs'
+import { dirname, relative, resolve } from 'node:path'
+import { fileURLToPath } from 'node:url'
+import { createRequire } from 'node:module'
 import { parseArgs } from 'node:util'
+import { watch } from 'rolldown'
+import polyfillNode from '@rolldown/plugin-node-polyfills'
+
+const require = createRequire(import.meta.url)
+const __dirname = dirname(fileURLToPath(import.meta.url))
+const fsShimPath = resolve(__dirname, 'shim-fs.js')
 
 const {
   values: { format: rawFormat, prod, inline: inlineDeps },
@@ -29,26 +37,133 @@ const {
 })
 
 const format = rawFormat || 'global'
-const target = positionals.length ? positionals[0] : 'vue'
-
-const [config, prodConfig] = createConfigsForPackage({
-  target,
-  commit: 'dev',
-  // @ts-expect-error
-  formats: [format],
-  devOnly: !prod,
-  sourceMap: true,
-  localDev: true,
-  inlineDeps,
-})
+const targets = positionals.length ? positionals : ['vue']
+
+const outputFormat = format.startsWith('global')
+  ? 'iife'
+  : format === 'cjs'
+    ? 'cjs'
+    : 'es'
 
-const configToUse = prod ? prodConfig : config
+const postfix = format.endsWith('-runtime')
+  ? `runtime.${format.replace(/-runtime$/, '')}`
+  : format
 
-// @ts-expect-error
-console.log(`watching: ${configToUse.output.file}`)
-watch(configToUse).on('event', event => {
-  if (event.code === 'BUNDLE_END') {
-    // @ts-expect-error
-    console.log(`rebuilt ${configToUse.output.file} in ${event.duration}ms`)
+const privatePackages = fs.readdirSync('packages-private')
+
+for (const target of targets) {
+  const pkgBase = privatePackages.includes(target)
+    ? `packages-private`
+    : `packages`
+  const pkgBasePath = `../${pkgBase}/${target}`
+  const pkg = require(`${pkgBasePath}/package.json`)
+  const outfile = resolve(
+    __dirname,
+    `${pkgBasePath}/dist/${
+      target === 'vue-compat' ? `vue` : target
+    }.${postfix}.${prod ? `prod.` : ``}js`,
+  )
+  const relativeOutfile = relative(process.cwd(), outfile)
+
+  /** @type {string[]} */
+  let external = []
+  if (!inlineDeps) {
+    if (format === 'cjs' || format.includes('esm-bundler')) {
+      external = [
+        ...external,
+        ...Object.keys(pkg.dependencies || {}),
+        ...Object.keys(pkg.peerDependencies || {}),
+        'path',
+        'url',
+        'stream',
+      ]
+    }
+
+    if (target === 'compiler-sfc') {
+      const consolidatePkgPath = require.resolve(
+        '@vue/consolidate/package.json',
+        {
+          paths: [resolve(__dirname, `../packages/${target}/`)],
+        },
+      )
+      const consolidateDeps = Object.keys(
+        require(consolidatePkgPath).devDependencies,
+      )
+      external = [
+        ...external,
+        ...consolidateDeps,
+        'react-dom/server',
+        'teacup/lib/express',
+        'arc-templates/dist/es5',
+        'then-pug',
+        'then-jade',
+      ]
+      if (format === 'cjs' || format.includes('esm-bundler')) {
+        external.push('fs', 'vm', 'crypto')
+      }
+    }
   }
-})
+
+  /** @type {import('rolldown').Plugin[]} */
+  const plugins = []
+  if (format !== 'cjs' && pkg.buildOptions?.enableNonBrowserBranches) {
+    plugins.push(polyfillNode())
+  }
+
+  const platform = format === 'cjs' ? 'node' : 'browser'
+  const resolveOptions =
+    format === 'cjs'
+      ? undefined
+      : {
+          alias: {
+            // Alias built-in fs to a shim for browser builds.
+            fs: fsShimPath,
+          },
+        }
+  /** @type {import('rolldown').WatchOptions} */
+  const config = {
+    input: resolve(__dirname, `${pkgBasePath}/src/index.ts`),
+    output: {
+      file: outfile,
+      format: outputFormat,
+      sourcemap: true,
+      name: format.startsWith('global') ? pkg.buildOptions?.name : undefined,
+    },
+    external,
+    platform,
+    resolve: resolveOptions,
+    treeshake: {
+      moduleSideEffects: false,
+    },
+    plugins,
+    transform: {
+      define: {
+        __COMMIT__: `"dev"`,
+        __VERSION__: `"${pkg.version}"`,
+        __DEV__: prod ? `false` : `true`,
+        __TEST__: `false`,
+        __BROWSER__: String(
+          format !== 'cjs' && !pkg.buildOptions?.enableNonBrowserBranches,
+        ),
+        __GLOBAL__: String(format === 'global'),
+        __ESM_BUNDLER__: String(format.includes('esm-bundler')),
+        __ESM_BROWSER__: String(format.includes('esm-browser')),
+        __CJS__: String(format === 'cjs'),
+        __SSR__: String(format !== 'global'),
+        __COMPAT__: String(target === 'vue-compat'),
+        __FEATURE_SUSPENSE__: `true`,
+        __FEATURE_OPTIONS_API__: `true`,
+        __FEATURE_PROD_DEVTOOLS__: `false`,
+        __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: `true`,
+      },
+    },
+  }
+
+  console.log(`watching: ${relativeOutfile}`)
+  watch(config).on('event', event => {
+    if (event.code === 'BUNDLE_END') {
+      // @ts-expect-error
+      console.log(`built ${config.output.file} in ${event.duration}ms`)
+    }
+  })
+}

+ 7 - 0
scripts/shim-fs.js

@@ -0,0 +1,7 @@
+// @ts-check
+export default {
+  existsSync: () => false,
+  readFileSync: () => {
+    throw new Error('fs.readFileSync is not supported in browser builds.')
+  },
+}