]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
build: use rolldown for dev script
authorEvan You <evan@vuejs.org>
Fri, 8 Nov 2024 11:55:14 +0000 (19:55 +0800)
committerEvan You <evan@vuejs.org>
Thu, 14 Nov 2024 12:58:14 +0000 (20:58 +0800)
scripts/build.js
scripts/create-rolldown-config.js
scripts/dev.js
scripts/inline-enums.js
scripts/verify-treeshaking.js

index a1b23ed6a901936d13c56dca0368f9b87976c417..f3d9127798fd67f9d4ec82de9519fd98fc7f4e3d 100644 (file)
@@ -16,6 +16,7 @@ nr build core --formats cjs
 ```
 */
 
+import { rolldown } from 'rolldown'
 import fs from 'node:fs'
 import { parseArgs } from 'node:util'
 import { existsSync, readFileSync } from 'node:fs'
@@ -26,7 +27,6 @@ import { targets as allTargets, fuzzyMatchTarget } from './utils.js'
 import prettyBytes from 'pretty-bytes'
 import { spawnSync } from 'node:child_process'
 import { createConfigsForPackage } from './create-rolldown-config.js'
-import { rolldown } from 'rolldown'
 import { scanEnums } from './inline-enums.js'
 import { fileURLToPath } from 'node:url'
 
index b5a5d80872dda52858ecbdc199361476b85af594..cdc2320a35789bcc5e9aeba09157280d68656035 100644 (file)
@@ -28,6 +28,8 @@ const packagesDir = path.resolve(__dirname, '../packages')
  *   devOnly?: boolean
  *   prodOnly?: boolean
  *   sourceMap?: boolean
+ *   localDev?: boolean
+ *   inlineDeps?: boolean
  * }} options
  */
 export function createConfigsForPackage({
@@ -37,8 +39,10 @@ export function createConfigsForPackage({
   devOnly = false,
   prodOnly = false,
   sourceMap = false,
+  localDev = false,
+  inlineDeps = false,
 }) {
-  const [enumPlugin, enumDefines] = inlineEnums()
+  const [enumPlugin, enumDefines] = localDev ? [] : inlineEnums()
 
   const packageDir = path.resolve(packagesDir, target)
   const resolve = (/** @type {string} */ p) => path.resolve(packageDir, p)
@@ -49,32 +53,32 @@ export function createConfigsForPackage({
   /** @type {Record<PackageFormat, import('rolldown').OutputOptions>} */
   const outputConfigs = {
     'esm-bundler': {
-      entryFileNames: `${name}.esm-bundler.js`,
+      file: `${name}.esm-bundler.js`,
       format: 'es',
     },
     'esm-browser': {
-      entryFileNames: `${name}.esm-browser.js`,
+      file: `${name}.esm-browser.js`,
       format: 'es',
     },
     cjs: {
-      entryFileNames: `${name}.cjs.js`,
+      file: `${name}.cjs.js`,
       format: 'cjs',
     },
     global: {
-      entryFileNames: `${name}.global.js`,
+      file: `${name}.global.js`,
       format: 'iife',
     },
     // runtime-only builds, for main "vue" package only
     'esm-bundler-runtime': {
-      entryFileNames: `${name}.runtime.esm-bundler.js`,
+      file: `${name}.runtime.esm-bundler.js`,
       format: 'es',
     },
     'esm-browser-runtime': {
-      entryFileNames: `${name}.runtime.esm-browser.js`,
+      file: `${name}.runtime.esm-browser.js`,
       format: 'es',
     },
     'global-runtime': {
-      entryFileNames: `${name}.runtime.global.js`,
+      file: `${name}.runtime.global.js`,
       format: 'iife',
     },
   }
@@ -117,9 +121,7 @@ export function createConfigsForPackage({
 
     output.dir = resolve('dist')
 
-    const isProductionBuild = /\.prod\.js$/.test(
-      String(output.entryFileNames) || '',
-    )
+    const isProductionBuild = /\.prod\.js$/.test(String(output.file) || '')
     const isBundlerESMBuild = /esm-bundler/.test(format)
     const isBrowserESMBuild = /esm-browser/.test(format)
     const isServerRenderer = name === 'server-renderer'
@@ -216,7 +218,7 @@ export function createConfigsForPackage({
       return defines
     }
 
-    // esbuild define is a bit strict and only allows literal json or identifiers
+    // define is a bit strict and only allows literal json or identifiers
     // so we still need replace plugin in some cases
     function resolveReplace() {
       /** @type {Record<string, string>} */
@@ -272,7 +274,7 @@ export function createConfigsForPackage({
         ]
       }
 
-      if (isGlobalBuild || isBrowserESMBuild || isCompatPackage) {
+      if (isGlobalBuild || isBrowserESMBuild || isCompatPackage || inlineDeps) {
         if (!packageOptions.enableNonBrowserBranches) {
           // normal browser builds - non-browser only imports are tree-shaken,
           // they are only listed here to suppress warnings.
@@ -314,9 +316,9 @@ export function createConfigsForPackage({
       resolve: {
         alias: entries,
       },
+      // @ts-expect-error rollup's Plugin type incompatible w/ rolldown's vendored Plugin type
       plugins: [
-        // @ts-expect-error rollup's Plugin type incompatible w/ rolldown's vendored Plugin type
-        enumPlugin,
+        ...(localDev ? [] : [enumPlugin]),
         ...resolveReplace(),
         ...resolveNodePlugins(),
         ...plugins,
@@ -336,7 +338,7 @@ export function createConfigsForPackage({
 
   function createProductionConfig(/** @type {PackageFormat} */ format) {
     return createConfig(format, {
-      entryFileNames: `${name}.${format}.prod.js`,
+      file: `${name}.${format}.prod.js`,
       format: outputConfigs[format].format,
     })
   }
@@ -345,10 +347,7 @@ export function createConfigsForPackage({
     return createConfig(
       format,
       {
-        entryFileNames: String(outputConfigs[format].entryFileNames).replace(
-          /\.js$/,
-          '.prod.js',
-        ),
+        file: String(outputConfigs[format].file).replace(/\.js$/, '.prod.js'),
         format: outputConfigs[format].format,
         // minify: true,
       },
index fb4d3873e8b90f5fd0401ded9cb4702bd3f09f92..afdba8981d9c378d82c555eb24a7b922488d5bf6 100644 (file)
@@ -1,19 +1,8 @@
 // @ts-check
 
-// Using esbuild for faster dev builds.
-// We are still using Rollup for production builds because it generates
-// smaller files and provides better tree-shaking.
-
-import esbuild from 'esbuild'
-import fs from 'node:fs'
-import { dirname, relative, resolve } from 'node:path'
-import { fileURLToPath } from 'node:url'
-import { createRequire } from 'node:module'
+import { watch } from 'rolldown'
+import { createConfigsForPackage } from './create-rolldown-config.js'
 import { parseArgs } from 'node:util'
-import { polyfillNode } from 'esbuild-plugin-polyfill-node'
-
-const require = createRequire(import.meta.url)
-const __dirname = dirname(fileURLToPath(import.meta.url))
 
 const {
   values: { format: rawFormat, prod, inline: inlineDeps },
@@ -40,123 +29,26 @@ const {
 })
 
 const format = rawFormat || 'global'
-const targets = positionals.length ? positionals : ['vue']
-
-// resolve output
-const outputFormat = format.startsWith('global')
-  ? 'iife'
-  : format === 'cjs'
-    ? 'cjs'
-    : 'esm'
-
-const postfix = format.endsWith('-runtime')
-  ? `runtime.${format.replace(/-runtime$/, '')}`
-  : format
-
-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)
+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,
+})
 
-  // resolve externals
-  // TODO this logic is largely duplicated from rollup.config.js
-  /** @type {string[]} */
-  let external = []
-  if (!inlineDeps) {
-    // cjs & esm-bundler: external all deps
-    if (format === 'cjs' || format.includes('esm-bundler')) {
-      external = [
-        ...external,
-        ...Object.keys(pkg.dependencies || {}),
-        ...Object.keys(pkg.peerDependencies || {}),
-        // for @vue/compiler-sfc / server-renderer
-        'path',
-        'url',
-        'stream',
-      ]
-    }
+const configToUse = prod ? prodConfig : config
 
-    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,
-        'fs',
-        'vm',
-        'crypto',
-        'react-dom/server',
-        'teacup/lib/express',
-        'arc-templates/dist/es5',
-        'then-pug',
-        'then-jade',
-      ]
+watch(configToUse).then(watcher => {
+  console.log(`watching: ${configToUse.output.file}`)
+  watcher.on('event', event => {
+    if (event.code === 'BUNDLE_END') {
+      console.log(`rebuilt ${config.output.file} in ${event.duration}ms`)
     }
-  }
-  /** @type {Array<import('esbuild').Plugin>} */
-  const plugins = [
-    {
-      name: 'log-rebuild',
-      setup(build) {
-        build.onEnd(() => {
-          console.log(`built: ${relativeOutfile}`)
-        })
-      },
-    },
-  ]
-
-  if (format !== 'cjs' && pkg.buildOptions?.enableNonBrowserBranches) {
-    plugins.push(polyfillNode())
-  }
-
-  esbuild
-    .context({
-      entryPoints: [resolve(__dirname, `${pkgBasePath}/src/index.ts`)],
-      outfile,
-      bundle: true,
-      external,
-      sourcemap: true,
-      format: outputFormat,
-      globalName: pkg.buildOptions?.name,
-      platform: format === 'cjs' ? 'node' : 'browser',
-      plugins,
-      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`,
-      },
-    })
-    .then(ctx => ctx.watch())
-}
+  })
+})
index 55583c10b4110418d85fed2d8bb4e6322deea3c8..88b2dca8c61be62e8410aeb0d93ef0049a45f647 100644 (file)
@@ -233,7 +233,7 @@ export function inlineEnums() {
 
   // 3. during transform:
   //    3.1 files w/ enum declaration: rewrite declaration as object literal
-  //    3.2 files using enum: inject into esbuild define
+  //    3.2 files using enum: inject into rolldown define
   /**
    * @type {import('rollup').Plugin}
    */
index 7cb76cdac8111fc6b6836b720ef3f0e0f35d58bc..783a4e9fc9a8b00fe16fcfbbe61565890b046755 100644 (file)
@@ -12,7 +12,7 @@ exec('pnpm', ['build', 'vue', '-f', 'global-runtime']).then(() => {
 
   if (devBuild.includes('__spreadValues')) {
     errors.push(
-      'dev build contains unexpected esbuild object spread helper.\n' +
+      'dev build contains unexpected object spread helper.\n' +
         'This means { ...obj } syntax is used in runtime code. This should be ' +
         'refactored to use the `extend` helper to avoid the extra code.',
     )