index.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. const path = require('path')
  2. const babel = require('@babel/core')
  3. const { isWindows } = require('@vue/cli-shared-utils')
  4. function getDepPathRegex (dependencies) {
  5. const deps = dependencies.map(dep => {
  6. if (typeof dep === 'string') {
  7. const depPath = path.join('node_modules', dep, '/')
  8. return isWindows
  9. ? depPath.replace(/\\/g, '\\\\') // double escape for windows style path
  10. : depPath
  11. } else if (dep instanceof RegExp) {
  12. return dep.source
  13. }
  14. throw new Error('transpileDependencies only accepts an array of string or regular expressions')
  15. })
  16. return deps.length ? new RegExp(deps.join('|')) : null
  17. }
  18. /** @type {import('@vue/cli-service').ServicePlugin} */
  19. module.exports = (api, options) => {
  20. const useThreads = process.env.NODE_ENV === 'production' && !!options.parallel
  21. const cliServicePath = path.dirname(require.resolve('@vue/cli-service'))
  22. // try to load the project babel config;
  23. // if the default preset is used,
  24. // there will be a VUE_CLI_TRANSPILE_BABEL_RUNTIME env var set.
  25. // the `filename` field is required
  26. // in case there're filename-related options like `ignore` in the user config
  27. babel.loadPartialConfigSync({ filename: api.resolve('src/main.js') })
  28. api.chainWebpack(webpackConfig => {
  29. webpackConfig.resolveLoader.modules.prepend(path.join(__dirname, 'node_modules'))
  30. const jsRule = webpackConfig.module
  31. .rule('js')
  32. .test(/\.m?jsx?$/)
  33. .exclude
  34. .add(filepath => {
  35. const SHOULD_SKIP = true
  36. const SHOULD_TRANSPILE = false
  37. // With data URI support in webpack 5, filepath could be undefined
  38. if (!filepath) {
  39. return SHOULD_SKIP
  40. }
  41. // Always transpile js in vue files
  42. if (/\.vue\.jsx?$/.test(filepath)) {
  43. return SHOULD_TRANSPILE
  44. }
  45. // Exclude dynamic entries from cli-service
  46. if (filepath.startsWith(cliServicePath)) {
  47. return SHOULD_SKIP
  48. }
  49. // To transpile `@babel/runtime`, the config needs to be
  50. // carefully adjusted to avoid infinite loops.
  51. // So we only do the tranpilation when the special flag is on.
  52. if (getDepPathRegex(['@babel/runtime']).test(filepath)) {
  53. return process.env.VUE_CLI_TRANSPILE_BABEL_RUNTIME
  54. ? SHOULD_TRANSPILE
  55. : SHOULD_SKIP
  56. }
  57. // if `transpileDependencies` is set to true, transpile all deps
  58. if (options.transpileDependencies === true) {
  59. // Some of the deps cannot be transpiled, though
  60. // https://stackoverflow.com/a/58517865/2302258
  61. const NON_TRANSPILABLE_DEPS = [
  62. 'core-js',
  63. 'webpack',
  64. 'webpack-4',
  65. 'css-loader',
  66. 'mini-css-extract-plugin',
  67. 'promise-polyfill',
  68. 'html-webpack-plugin',
  69. 'whatwg-fetch'
  70. ]
  71. const nonTranspilableDepsRegex = getDepPathRegex(NON_TRANSPILABLE_DEPS)
  72. return nonTranspilableDepsRegex.test(filepath) ? SHOULD_SKIP : SHOULD_TRANSPILE
  73. }
  74. // Otherwise, check if this is something the user explicitly wants to transpile
  75. if (Array.isArray(options.transpileDependencies)) {
  76. const transpileDepRegex = getDepPathRegex(options.transpileDependencies)
  77. if (transpileDepRegex && transpileDepRegex.test(filepath)) {
  78. return SHOULD_TRANSPILE
  79. }
  80. }
  81. // Don't transpile node_modules
  82. return /node_modules/.test(filepath) ? SHOULD_SKIP : SHOULD_TRANSPILE
  83. })
  84. .end()
  85. if (useThreads) {
  86. const threadLoaderConfig = jsRule
  87. .use('thread-loader')
  88. .loader(require.resolve('thread-loader'))
  89. if (typeof options.parallel === 'number') {
  90. threadLoaderConfig.options({ workers: options.parallel })
  91. }
  92. }
  93. jsRule
  94. .use('babel-loader')
  95. .loader(require.resolve('babel-loader'))
  96. .options({
  97. cacheCompression: false,
  98. ...api.genCacheConfig('babel-loader', {
  99. '@babel/core': require('@babel/core/package.json').version,
  100. '@vue/babel-preset-app': require('@vue/babel-preset-app/package.json').version,
  101. 'babel-loader': require('babel-loader/package.json').version,
  102. modern: !!process.env.VUE_CLI_MODERN_BUILD,
  103. browserslist: api.service.pkg.browserslist
  104. }, [
  105. 'babel.config.js',
  106. '.browserslistrc'
  107. ])
  108. })
  109. })
  110. }