rollup-plugin-deps.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * @Author: Rindy
  3. * @Date: 2021-04-29 14:23:36
  4. * @LastEditors: Rindy
  5. * @LastEditTime: 2021-05-24 17:28:29
  6. * @Description: 注释
  7. */
  8. import deps from '@kankan/sdk-deps'
  9. import { minify } from 'terser'
  10. import path from 'path'
  11. import util from 'util'
  12. import fs from 'fs-extra'
  13. import isObject from 'is-plain-object'
  14. import globby from 'globby'
  15. import { bold, green, yellow } from 'colorette'
  16. function stringify(value) {
  17. return util.inspect(value, { breakLength: Infinity })
  18. }
  19. async function isFile(filePath) {
  20. const fileStats = await fs.stat(filePath)
  21. return fileStats.isFile()
  22. }
  23. function renameTarget(target, rename, src) {
  24. const parsedPath = path.parse(target)
  25. return typeof rename === 'string' ? rename : rename(parsedPath.name, parsedPath.ext.replace('.', ''), src)
  26. }
  27. async function generateCopyTarget(src, dest, { flatten, rename, transform }) {
  28. if (transform && !(await isFile(src))) {
  29. throw new Error(`"transform" option works only on files: '${src}' must be a file`)
  30. }
  31. const { base, dir } = path.parse(src)
  32. const destinationFolder = flatten || (!flatten && !dir) ? dest : dir.replace(dir.split('/')[0], dest)
  33. return {
  34. src,
  35. dest: path.join(destinationFolder, rename ? renameTarget(base, rename, src) : base),
  36. ...(transform && { contents: await transform(await fs.readFile(src), base) }),
  37. renamed: rename,
  38. transformed: transform,
  39. }
  40. }
  41. export default function (options = {}) {
  42. const { mangle, copyOnce = false, flatten = true, hook = 'buildEnd', copy = {}, verbose = false, ...restPluginOptions } = options
  43. let copied = false
  44. return {
  45. name: 'rollup-plugin-deps', // 这个名字将会出现在在警告和报错中
  46. resolveId(importee) {
  47. if (importee.indexOf('sdk-deps.js') != -1) {
  48. return importee
  49. }
  50. return null // 其他的id不受影响
  51. },
  52. load(id) {
  53. if (id.indexOf('sdk-deps.js') != -1) {
  54. return ''
  55. }
  56. return null // 其他的id还是通过正常的方式解析
  57. },
  58. async buildEnd() {
  59. if (copyOnce && copied) {
  60. return
  61. }
  62. const targets = copy.targets || []
  63. const copyTargets = []
  64. if (Array.isArray(targets) && targets.length) {
  65. for (const target of targets) {
  66. if (!isObject(target)) {
  67. throw new Error(`${stringify(target)} target must be an object`)
  68. }
  69. const { dest, rename, name, transform, ...restTargetOptions } = target
  70. const src = deps[name]
  71. if (!src || !dest) {
  72. throw new Error(`${stringify(target)} target must have "src" and "dest" properties`)
  73. }
  74. if (rename && typeof rename !== 'string' && typeof rename !== 'function') {
  75. throw new Error(`${stringify(target)} target's "rename" property must be a string or a function`)
  76. }
  77. const matchedPaths = await globby(src, {
  78. expandDirectories: false,
  79. onlyFiles: false,
  80. ...restPluginOptions,
  81. ...restTargetOptions,
  82. })
  83. if (matchedPaths.length) {
  84. for (const matchedPath of matchedPaths) {
  85. const generatedCopyTargets = Array.isArray(dest)
  86. ? await Promise.all(dest.map(destination => generateCopyTarget(matchedPath, destination, { flatten, rename, transform })))
  87. : [await generateCopyTarget(matchedPath, dest, { flatten, rename, transform })]
  88. copyTargets.push(...generatedCopyTargets)
  89. }
  90. }
  91. }
  92. }
  93. if (copyTargets.length) {
  94. console.log(green('正在复制'))
  95. if (verbose) {
  96. console.log(green('copied:'))
  97. }
  98. for (const copyTarget of copyTargets) {
  99. const { contents, dest, src, transformed } = copyTarget
  100. if (transformed) {
  101. await fs.outputFile(dest, contents, restPluginOptions)
  102. } else {
  103. await fs.copy(src, dest, restPluginOptions)
  104. }
  105. if (verbose) {
  106. let message = green(` ${bold(src)} → ${bold(dest)}`)
  107. const flags = Object.entries(copyTarget)
  108. .filter(([key, value]) => ['renamed', 'transformed'].includes(key) && value)
  109. .map(([key]) => key.charAt(0).toUpperCase())
  110. if (flags.length) {
  111. message = `${message} ${yellow(`[${flags.join(', ')}]`)}`
  112. }
  113. console.log(message)
  114. }
  115. }
  116. console.log(green('完成复制'))
  117. } else if (verbose) {
  118. console.log(yellow('no items to copy'))
  119. }
  120. copied = true
  121. },
  122. transform(source, id) {},
  123. buildStart() {},
  124. async generateBundle(options, bundle, isWrite) {
  125. console.log(green('正在压缩依赖'))
  126. const source = []
  127. for (let i = 0; i < deps.js.length; i++) {
  128. let file = deps.js[i]
  129. if (fs.existsSync(file)) {
  130. let code = fs.readFileSync(file).toString()
  131. if (!/\.(min|prod)\.js$/.test(file)) {
  132. if (mangle) {
  133. code = (await minify(code, { mangle: true })).code
  134. }
  135. }
  136. source.push(code)
  137. }
  138. }
  139. this.emitFile({ type: 'asset', fileName: options.file.replace(/\\/g, '/').split('/').pop(), source: source.join(';\r\n') })
  140. console.log(green('完成压缩依赖'))
  141. },
  142. }
  143. }