dev.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // @ts-check
  2. import fs from 'node:fs'
  3. import { dirname, relative, resolve } from 'node:path'
  4. import { fileURLToPath } from 'node:url'
  5. import { createRequire } from 'node:module'
  6. import { parseArgs } from 'node:util'
  7. import { watch } from 'rolldown'
  8. import polyfillNode from '@rolldown/plugin-node-polyfills'
  9. const require = createRequire(import.meta.url)
  10. const __dirname = dirname(fileURLToPath(import.meta.url))
  11. const fsShimPath = resolve(__dirname, 'shim-fs.js')
  12. const {
  13. values: { format: rawFormat, prod, inline: inlineDeps },
  14. positionals,
  15. } = parseArgs({
  16. allowPositionals: true,
  17. options: {
  18. format: {
  19. type: 'string',
  20. short: 'f',
  21. default: 'global',
  22. },
  23. prod: {
  24. type: 'boolean',
  25. short: 'p',
  26. default: false,
  27. },
  28. inline: {
  29. type: 'boolean',
  30. short: 'i',
  31. default: false,
  32. },
  33. },
  34. })
  35. const format = rawFormat || 'global'
  36. const targets = positionals.length ? positionals : ['vue']
  37. const outputFormat = format.startsWith('global')
  38. ? 'iife'
  39. : format === 'cjs'
  40. ? 'cjs'
  41. : 'es'
  42. const postfix = format.endsWith('-runtime')
  43. ? `runtime.${format.replace(/-runtime$/, '')}`
  44. : format
  45. const privatePackages = fs.readdirSync('packages-private')
  46. for (const target of targets) {
  47. const pkgBase = privatePackages.includes(target)
  48. ? `packages-private`
  49. : `packages`
  50. const pkgBasePath = `../${pkgBase}/${target}`
  51. const pkg = require(`${pkgBasePath}/package.json`)
  52. const isVueEsmBrowserVapor =
  53. pkg.name === 'vue' && format === 'esm-browser-vapor'
  54. const outfile = resolve(
  55. __dirname,
  56. `${pkgBasePath}/dist/${target === 'vue-compat' ? `vue` : target}.${
  57. isVueEsmBrowserVapor ? `runtime-with-vapor.esm-browser` : postfix
  58. }.${prod ? `prod.` : ``}js`,
  59. )
  60. const relativeOutfile = relative(process.cwd(), outfile)
  61. let entryFile = 'index.ts'
  62. if (pkg.name === 'vue') {
  63. if (format === 'esm-browser-vapor' || format === 'esm-bundler-runtime') {
  64. entryFile = 'runtime-with-vapor.ts'
  65. } else if (format === 'esm-bundler') {
  66. entryFile = 'index-with-vapor.ts'
  67. } else if (format.includes('runtime')) {
  68. entryFile = 'runtime.ts'
  69. }
  70. }
  71. /** @type {string[]} */
  72. let external = []
  73. if (!inlineDeps) {
  74. if (format === 'cjs' || format.includes('esm-bundler')) {
  75. external = [
  76. ...external,
  77. ...Object.keys(pkg.dependencies || {}),
  78. ...Object.keys(pkg.peerDependencies || {}),
  79. 'path',
  80. 'url',
  81. 'stream',
  82. ]
  83. }
  84. if (target === 'compiler-sfc') {
  85. const consolidatePkgPath = require.resolve(
  86. '@vue/consolidate/package.json',
  87. {
  88. paths: [resolve(__dirname, `../packages/${target}/`)],
  89. },
  90. )
  91. const consolidateDeps = Object.keys(
  92. require(consolidatePkgPath).devDependencies,
  93. )
  94. external = [
  95. ...external,
  96. ...consolidateDeps,
  97. 'react-dom/server',
  98. 'teacup/lib/express',
  99. 'arc-templates/dist/es5',
  100. 'then-pug',
  101. 'then-jade',
  102. ]
  103. if (format === 'cjs' || format.includes('esm-bundler')) {
  104. external.push('fs', 'vm', 'crypto')
  105. }
  106. }
  107. }
  108. /** @type {import('rolldown').Plugin[]} */
  109. const plugins = []
  110. if (format !== 'cjs' && pkg.buildOptions?.enableNonBrowserBranches) {
  111. plugins.push(polyfillNode())
  112. }
  113. const platform = format === 'cjs' ? 'node' : 'browser'
  114. const resolveOptions =
  115. format === 'cjs'
  116. ? undefined
  117. : {
  118. alias: {
  119. // Alias built-in fs to a shim for browser builds.
  120. fs: fsShimPath,
  121. },
  122. }
  123. /** @type {import('rolldown').WatchOptions} */
  124. const config = {
  125. input: resolve(__dirname, `${pkgBasePath}/src/${entryFile}`),
  126. output: {
  127. file: outfile,
  128. format: outputFormat,
  129. sourcemap: true,
  130. name: format.startsWith('global') ? pkg.buildOptions?.name : undefined,
  131. },
  132. external,
  133. platform,
  134. resolve: resolveOptions,
  135. treeshake: {
  136. moduleSideEffects: false,
  137. },
  138. plugins,
  139. transform: {
  140. define: {
  141. __COMMIT__: `"dev"`,
  142. __VERSION__: `"${pkg.version}"`,
  143. __DEV__: prod ? `false` : `true`,
  144. __TEST__: `false`,
  145. __E2E_TEST__: `false`,
  146. __BROWSER__: String(
  147. format !== 'cjs' && !pkg.buildOptions?.enableNonBrowserBranches,
  148. ),
  149. __GLOBAL__: String(format === 'global'),
  150. __ESM_BUNDLER__: String(format.includes('esm-bundler')),
  151. __ESM_BROWSER__: String(format.includes('esm-browser')),
  152. __CJS__: String(format === 'cjs'),
  153. __SSR__: String(format !== 'global'),
  154. __COMPAT__: String(target === 'vue-compat'),
  155. __FEATURE_SUSPENSE__: `true`,
  156. __FEATURE_OPTIONS_API__: `true`,
  157. __FEATURE_PROD_DEVTOOLS__: `false`,
  158. __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: `true`,
  159. },
  160. },
  161. }
  162. console.log(`watching: ${relativeOutfile}`)
  163. watch(config).on('event', event => {
  164. if (event.code === 'BUNDLE_END') {
  165. // @ts-expect-error
  166. console.log(`built ${config.output.file} in ${event.duration}ms`)
  167. }
  168. })
  169. }