rollup.config.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. const fs = require('fs')
  2. const path = require('path')
  3. const ts = require('rollup-plugin-typescript2')
  4. const replace = require('rollup-plugin-replace')
  5. const alias = require('rollup-plugin-alias')
  6. if (!process.env.TARGET) {
  7. throw new Error('TARGET package must be specified via --environment flag.')
  8. }
  9. const packagesDir = path.resolve(__dirname, 'packages')
  10. const packageDir = path.resolve(packagesDir, process.env.TARGET)
  11. const name = path.basename(packageDir)
  12. const resolve = p => path.resolve(packageDir, p)
  13. const pkg = require(resolve(`package.json`))
  14. const packageOptions = pkg.buildOptions || {}
  15. // build aliases dynamically
  16. const aliasOptions = { resolve: ['.ts'] }
  17. fs.readdirSync(packagesDir).forEach(dir => {
  18. if (
  19. !dir.startsWith('vue') &&
  20. fs.statSync(path.resolve(packagesDir, dir)).isDirectory()
  21. ) {
  22. aliasOptions[`@vue/${dir}`] = path.resolve(packagesDir, `${dir}/src/index`)
  23. }
  24. })
  25. const aliasPlugin = alias(aliasOptions)
  26. // ensure TS checks only once for each build
  27. let hasTSChecked = false
  28. const configs = {
  29. esm: {
  30. file: resolve(`dist/${name}.esm-bundler.js`),
  31. format: `es`
  32. },
  33. cjs: {
  34. file: resolve(`dist/${name}.cjs.js`),
  35. format: `cjs`
  36. },
  37. global: {
  38. file: resolve(`dist/${name}.global.js`),
  39. format: `iife`
  40. },
  41. 'esm-browser': {
  42. file: resolve(`dist/${name}.esm-browser.js`),
  43. format: `es`
  44. }
  45. }
  46. const defaultFormats = ['esm', 'cjs']
  47. const inlineFromats = process.env.FORMATS && process.env.FORMATS.split(',')
  48. const packageFormats = inlineFromats || packageOptions.formats || defaultFormats
  49. const packageConfigs = packageFormats.map(format =>
  50. createConfig(configs[format])
  51. )
  52. if (process.env.NODE_ENV === 'production') {
  53. packageFormats.forEach(format => {
  54. if (format === 'cjs') {
  55. packageConfigs.push(createProductionConfig(format))
  56. }
  57. if (format === 'global' || format === 'esm-browser') {
  58. packageConfigs.push(createMinifiedConfig(format))
  59. }
  60. })
  61. }
  62. module.exports = packageConfigs
  63. function createConfig(output, plugins = []) {
  64. const isProductionBuild =
  65. process.env.__DEV__ === 'false' || /\.prod\.js$/.test(output.file)
  66. const isGlobalBuild = /\.global(\.prod)?\.js$/.test(output.file)
  67. const isBunlderESMBuild = /\.esm\.js$/.test(output.file)
  68. const isBrowserESMBuild = /esm-browser(\.prod)?\.js$/.test(output.file)
  69. if (isGlobalBuild) {
  70. output.name = packageOptions.name
  71. }
  72. const shouldEmitDeclarations =
  73. process.env.TYPES != null &&
  74. process.env.NODE_ENV === 'production' &&
  75. !hasTSChecked
  76. const tsPlugin = ts({
  77. check: process.env.NODE_ENV === 'production' && !hasTSChecked,
  78. tsconfig: path.resolve(__dirname, 'tsconfig.json'),
  79. cacheRoot: path.resolve(__dirname, 'node_modules/.rts2_cache'),
  80. tsconfigOverride: {
  81. compilerOptions: {
  82. declaration: shouldEmitDeclarations,
  83. declarationMap: shouldEmitDeclarations
  84. }
  85. }
  86. })
  87. // we only need to check TS and generate declarations once for each build.
  88. // it also seems to run into weird issues when checking multiple times
  89. // during a single build.
  90. hasTSChecked = true
  91. const externals = Object.keys(aliasOptions).filter(p => p !== '@vue/shared')
  92. return {
  93. input: resolve(`src/index.ts`),
  94. // Global and Browser ESM builds inlines everything so that they can be
  95. // used alone.
  96. external: isGlobalBuild || isBrowserESMBuild ? [] : externals,
  97. plugins: [
  98. tsPlugin,
  99. aliasPlugin,
  100. createReplacePlugin(
  101. isProductionBuild,
  102. isBunlderESMBuild,
  103. isGlobalBuild || isBrowserESMBuild
  104. ),
  105. ...plugins
  106. ],
  107. output,
  108. onwarn: (msg, warn) => {
  109. if (!/Circular/.test(msg)) {
  110. warn(msg)
  111. }
  112. }
  113. }
  114. }
  115. function createReplacePlugin(isProduction, isBunlderESMBuild, isBrowserBuild) {
  116. return replace({
  117. __DEV__: isBunlderESMBuild
  118. ? // preserve to be handled by bundlers
  119. `process.env.NODE_ENV !== 'production'`
  120. : // hard coded dev/prod builds
  121. !isProduction,
  122. // show production tip?
  123. // should only do this for dev AND browser-targeting builds.
  124. __FEATURE_PRODUCTION_TIP__: !isProduction && isBrowserBuild,
  125. // support options?
  126. // the lean build drops options related code with buildOptions.lean: true
  127. __FEATURE_OPTIONS__: !packageOptions.lean,
  128. // this is only used during tests
  129. __JSDOM__: false
  130. })
  131. }
  132. function createProductionConfig(format) {
  133. return createConfig({
  134. file: resolve(`dist/${name}.${format}.prod.js`),
  135. format: configs[format].format
  136. })
  137. }
  138. function createMinifiedConfig(format) {
  139. const { terser } = require('rollup-plugin-terser')
  140. return createConfig(
  141. {
  142. file: resolve(`dist/${name}.${format}.prod.js`),
  143. format: configs[format].format
  144. },
  145. [
  146. terser({
  147. module: /^esm/.test(format)
  148. })
  149. ]
  150. )
  151. }