2
0

dev.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. // @ts-check
  2. // Using esbuild for faster dev builds.
  3. // We are still using Rollup for production builds because it generates
  4. // smaller files and provides better tree-shaking.
  5. import esbuild from 'esbuild'
  6. import fs from 'node:fs'
  7. import { dirname, relative, resolve } from 'node:path'
  8. import { fileURLToPath } from 'node:url'
  9. import { createRequire } from 'node:module'
  10. import { parseArgs } from 'node:util'
  11. import { polyfillNode } from 'esbuild-plugin-polyfill-node'
  12. const require = createRequire(import.meta.url)
  13. const __dirname = dirname(fileURLToPath(import.meta.url))
  14. const {
  15. values: { format: rawFormat, prod, inline: inlineDeps },
  16. positionals,
  17. } = parseArgs({
  18. allowPositionals: true,
  19. options: {
  20. format: {
  21. type: 'string',
  22. short: 'f',
  23. default: 'global',
  24. },
  25. prod: {
  26. type: 'boolean',
  27. short: 'p',
  28. default: false,
  29. },
  30. inline: {
  31. type: 'boolean',
  32. short: 'i',
  33. default: false,
  34. },
  35. },
  36. })
  37. const format = rawFormat || 'global'
  38. const targets = positionals.length ? positionals : ['vue']
  39. // resolve output
  40. const outputFormat = format.startsWith('global')
  41. ? 'iife'
  42. : format === 'cjs'
  43. ? 'cjs'
  44. : 'esm'
  45. const postfix =
  46. format === 'esm-browser-vapor'
  47. ? 'runtime-with-vapor.esm-browser'
  48. : format.endsWith('-runtime')
  49. ? `runtime.${format.replace(/-runtime$/, '')}`
  50. : format
  51. const privatePackages = fs.readdirSync('packages-private')
  52. for (const target of targets) {
  53. const pkgBase = privatePackages.includes(target)
  54. ? `packages-private`
  55. : `packages`
  56. const pkgBasePath = `../${pkgBase}/${target}`
  57. const pkg = require(`${pkgBasePath}/package.json`)
  58. const outfile = resolve(
  59. __dirname,
  60. `${pkgBasePath}/dist/${
  61. target === 'vue-compat' ? `vue` : target
  62. }.${postfix}.${prod ? `prod.` : ``}js`,
  63. )
  64. const relativeOutfile = relative(process.cwd(), outfile)
  65. // resolve externals
  66. // TODO this logic is largely duplicated from rollup.config.js
  67. /** @type {string[]} */
  68. let external = []
  69. if (!inlineDeps) {
  70. // cjs & esm-bundler: external all deps
  71. if (format === 'cjs' || format.includes('esm-bundler')) {
  72. external = [
  73. ...external,
  74. ...Object.keys(pkg.dependencies || {}),
  75. ...Object.keys(pkg.peerDependencies || {}),
  76. // for @vue/compiler-sfc / server-renderer
  77. 'path',
  78. 'url',
  79. 'stream',
  80. ]
  81. }
  82. if (target === 'compiler-sfc') {
  83. const consolidatePkgPath = require.resolve(
  84. '@vue/consolidate/package.json',
  85. {
  86. paths: [resolve(__dirname, `../packages/${target}/`)],
  87. },
  88. )
  89. const consolidateDeps = Object.keys(
  90. require(consolidatePkgPath).devDependencies,
  91. )
  92. external = [
  93. ...external,
  94. ...consolidateDeps,
  95. 'fs',
  96. 'vm',
  97. 'crypto',
  98. 'react-dom/server',
  99. 'teacup/lib/express',
  100. 'arc-templates/dist/es5',
  101. 'then-pug',
  102. 'then-jade',
  103. ]
  104. }
  105. }
  106. /** @type {Array<import('esbuild').Plugin>} */
  107. const plugins = [
  108. {
  109. name: 'log-rebuild',
  110. setup(build) {
  111. build.onEnd(() => {
  112. console.log(`built: ${relativeOutfile}`)
  113. })
  114. },
  115. },
  116. ]
  117. if (format !== 'cjs' && pkg.buildOptions?.enableNonBrowserBranches) {
  118. plugins.push(polyfillNode())
  119. }
  120. const entry =
  121. format === 'esm-browser-vapor'
  122. ? 'runtime-with-vapor.ts'
  123. : format.endsWith('-runtime')
  124. ? 'runtime.ts'
  125. : 'index.ts'
  126. esbuild
  127. .context({
  128. entryPoints: [resolve(__dirname, `${pkgBasePath}/src/${entry}`)],
  129. outfile,
  130. bundle: true,
  131. external,
  132. sourcemap: true,
  133. format: outputFormat,
  134. globalName: pkg.buildOptions?.name,
  135. platform: format === 'cjs' ? 'node' : 'browser',
  136. plugins,
  137. define: {
  138. __COMMIT__: `"dev"`,
  139. __VERSION__: `"${pkg.version}"`,
  140. __DEV__: prod ? `false` : `true`,
  141. __TEST__: `false`,
  142. __BROWSER__: String(
  143. format !== 'cjs' && !pkg.buildOptions?.enableNonBrowserBranches,
  144. ),
  145. __GLOBAL__: String(format === 'global'),
  146. __ESM_BUNDLER__: String(format.includes('esm-bundler')),
  147. __ESM_BROWSER__: String(format.includes('esm-browser')),
  148. __CJS__: String(format === 'cjs'),
  149. __SSR__: String(format !== 'global'),
  150. __BENCHMARK__: process.env.BENCHMARK || 'false',
  151. __COMPAT__: String(target === 'vue-compat'),
  152. __FEATURE_SUSPENSE__: `true`,
  153. __FEATURE_OPTIONS_API__: `true`,
  154. __FEATURE_PROD_DEVTOOLS__: `false`,
  155. __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: `true`,
  156. },
  157. })
  158. .then(ctx => ctx.watch())
  159. }