index.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. const path = require('path')
  2. const defaultPolyfills = [
  3. // promise polyfill alone doesn't work in IE,
  4. // needs this as well. see: #1642
  5. 'es6.array.iterator',
  6. // this is required for webpack code splitting, vuex etc.
  7. 'es6.promise',
  8. // this is needed for object rest spread support in templates
  9. // as vue-template-es2015-compiler 1.8+ compiles it to Object.assign() calls.
  10. 'es6.object.assign',
  11. // #2012 es6.promise replaces native Promise in FF and causes missing finally
  12. 'es7.promise.finally'
  13. ]
  14. function getPolyfills (targets, includes, { ignoreBrowserslistConfig, configPath }) {
  15. const { isPluginRequired } = require('@babel/preset-env')
  16. const builtInsList = require('@babel/preset-env/data/built-ins.json')
  17. const getTargets = require('@babel/preset-env/lib/targets-parser').default
  18. const builtInTargets = getTargets(targets, {
  19. ignoreBrowserslistConfig,
  20. configPath
  21. })
  22. return includes.filter(item => {
  23. return isPluginRequired(builtInTargets, builtInsList[item])
  24. })
  25. }
  26. module.exports = (context, options = {}) => {
  27. const presets = []
  28. const plugins = []
  29. const defaultEntryFiles = JSON.parse(process.env.VUE_CLI_ENTRY_FILES || '[]')
  30. // JSX
  31. if (options.jsx !== false) {
  32. presets.push([require('@vue/babel-preset-jsx'), typeof options.jsx === 'object' ? options.jsx : {}])
  33. }
  34. const runtimePath = path.dirname(require.resolve('@babel/runtime/package.json'))
  35. const {
  36. polyfills: userPolyfills,
  37. loose = false,
  38. debug = false,
  39. useBuiltIns = 'usage',
  40. modules = false,
  41. targets: rawTargets,
  42. spec,
  43. ignoreBrowserslistConfig = !!process.env.VUE_CLI_MODERN_BUILD,
  44. configPath,
  45. include,
  46. exclude,
  47. shippedProposals,
  48. forceAllTransforms,
  49. decoratorsBeforeExport,
  50. decoratorsLegacy,
  51. // entry file list
  52. entryFiles = defaultEntryFiles,
  53. // Undocumented option of @babel/plugin-transform-runtime.
  54. // When enabled, an absolute path is used when importing a runtime helper atfer tranforming.
  55. // This ensures the transpiled file always use the runtime version required in this package.
  56. // However, this may cause hash inconsitency if the project is moved to another directory.
  57. // So here we allow user to explicit disable this option if hash consistency is a requirement
  58. // and the runtime version is sure to be correct.
  59. absoluteRuntime = runtimePath
  60. } = options
  61. // resolve targets
  62. let targets
  63. if (process.env.VUE_CLI_BABEL_TARGET_NODE) {
  64. // running tests in Node.js
  65. targets = { node: 'current' }
  66. } else if (process.env.VUE_CLI_BUILD_TARGET === 'wc' || process.env.VUE_CLI_BUILD_TARGET === 'wc-async') {
  67. // targeting browsers that at least support ES2015 classes
  68. // https://github.com/babel/babel/blob/master/packages/babel-preset-env/data/plugins.json#L52-L61
  69. targets = {
  70. browsers: [
  71. 'Chrome >= 49',
  72. 'Firefox >= 45',
  73. 'Safari >= 10',
  74. 'Edge >= 13',
  75. 'iOS >= 10',
  76. 'Electron >= 0.36'
  77. ]
  78. }
  79. } else if (process.env.VUE_CLI_MODERN_BUILD) {
  80. // targeting browsers that support <script type="module">
  81. targets = { esmodules: true }
  82. } else {
  83. targets = rawTargets
  84. }
  85. // included-by-default polyfills. These are common polyfills that 3rd party
  86. // dependencies may rely on (e.g. Vuex relies on Promise), but since with
  87. // useBuiltIns: 'usage' we won't be running Babel on these deps, they need to
  88. // be force-included.
  89. let polyfills
  90. const buildTarget = process.env.VUE_CLI_BUILD_TARGET || 'app'
  91. if (
  92. buildTarget === 'app' &&
  93. useBuiltIns === 'usage' &&
  94. !process.env.VUE_CLI_BABEL_TARGET_NODE &&
  95. !process.env.VUE_CLI_MODERN_BUILD
  96. ) {
  97. polyfills = getPolyfills(targets, userPolyfills || defaultPolyfills, {
  98. ignoreBrowserslistConfig,
  99. configPath
  100. })
  101. plugins.push([
  102. require('./polyfillsPlugin'),
  103. { polyfills, entryFiles, useAbsolutePath: !!absoluteRuntime }
  104. ])
  105. } else {
  106. polyfills = []
  107. }
  108. const envOptions = {
  109. spec,
  110. loose,
  111. debug,
  112. modules,
  113. targets,
  114. useBuiltIns,
  115. ignoreBrowserslistConfig,
  116. configPath,
  117. include,
  118. exclude: polyfills.concat(exclude || []),
  119. shippedProposals,
  120. forceAllTransforms
  121. }
  122. // cli-plugin-jest sets this to true because Jest runs without bundling
  123. if (process.env.VUE_CLI_BABEL_TRANSPILE_MODULES) {
  124. envOptions.modules = 'commonjs'
  125. // necessary for dynamic import to work in tests
  126. plugins.push(require('babel-plugin-dynamic-import-node'))
  127. }
  128. // pass options along to babel-preset-env
  129. presets.unshift([require('@babel/preset-env'), envOptions])
  130. // additional <= stage-3 plugins
  131. // Babel 7 is removing stage presets altogether because people are using
  132. // too many unstable proposals. Let's be conservative in the defaults here.
  133. plugins.push(
  134. require('@babel/plugin-syntax-dynamic-import'),
  135. [require('@babel/plugin-proposal-decorators'), {
  136. decoratorsBeforeExport,
  137. legacy: decoratorsLegacy !== false
  138. }],
  139. [require('@babel/plugin-proposal-class-properties'), { loose }],
  140. )
  141. // transform runtime, but only for helpers
  142. plugins.push([require('@babel/plugin-transform-runtime'), {
  143. regenerator: useBuiltIns !== 'usage',
  144. // polyfills are injected by preset-env & polyfillsPlugin, so no need to add them again
  145. corejs: false,
  146. helpers: useBuiltIns === 'usage',
  147. useESModules: !process.env.VUE_CLI_BABEL_TRANSPILE_MODULES,
  148. absoluteRuntime
  149. }])
  150. // use @babel/runtime-corejs2 so that helpers that need polyfillable APIs will reference core-js instead.
  151. // if useBuiltIns is not set to 'usage', then it means users would take care of the polyfills on their own,
  152. // i.e., core-js is no longer needed.
  153. // this extra plugin can be removed once one of the two issues resolves:
  154. // https://github.com/babel/babel/issues/7597
  155. // https://github.com/babel/babel/issues/9903
  156. if (useBuiltIns === 'usage' && !process.env.VUE_CLI_MODERN_BUILD) {
  157. const runtimeCoreJs2Path = path.dirname(require.resolve('@babel/runtime-corejs2/package.json'))
  158. plugins.push([require('babel-plugin-module-resolver'), {
  159. alias: {
  160. '@babel/runtime': '@babel/runtime-corejs2',
  161. [runtimePath]: runtimeCoreJs2Path
  162. }
  163. }])
  164. }
  165. return {
  166. presets,
  167. plugins
  168. }
  169. }