* devOnly?: boolean
* prodOnly?: boolean
* sourceMap?: boolean
+ * localDev?: boolean
+ * inlineDeps?: boolean
* }} options
*/
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)
/** @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',
},
}
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'
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>} */
]
}
- 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.
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,
function createProductionConfig(/** @type {PackageFormat} */ format) {
return createConfig(format, {
- entryFileNames: `${name}.${format}.prod.js`,
+ file: `${name}.${format}.prod.js`,
format: outputConfigs[format].format,
})
}
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,
},
// @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 },
})
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())
-}
+ })
+})