You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /**
  2. @author : Caven Chen
  3. **/
  4. 'use strict'
  5. import fse from 'fs-extra'
  6. import path from 'path'
  7. import gulp from 'gulp'
  8. import esbuild from 'esbuild'
  9. import concat from 'gulp-concat'
  10. import clean from 'gulp-clean'
  11. import javascriptObfuscator from 'gulp-javascript-obfuscator'
  12. import startServer from './server.js'
  13. import inlineImage from 'esbuild-plugin-inline-image'
  14. import { sassPlugin } from 'esbuild-sass-plugin'
  15. import { glsl } from 'esbuild-plugin-glsl'
  16. import shell from 'shelljs'
  17. import chalk from 'chalk'
  18. const dc_common_path = './node_modules/@dvgis/dc-common'
  19. const packageJson = fse.readJsonSync('./package.json')
  20. const c_packageJson = fse.readJsonSync(
  21. path.join(dc_common_path, 'package.json')
  22. )
  23. const obfuscatorConfig = {
  24. compact: true, //压缩代码
  25. identifierNamesGenerator: 'hexadecimal', //标识符的混淆方式 hexadecimal(十六进制) mangled(短标识符)
  26. renameGlobals: false, //是否启用全局变量和函数名称的混淆
  27. rotateStringArray: true, //通过固定和随机(在代码混淆时生成)的位置移动数组。这使得将删除的字符串的顺序与其原始位置相匹配变得更加困难。如果原始源代码不小,建议使用此选项,因为辅助函数可以引起注意。
  28. selfDefending: true, //混淆后的代码,不能使用代码美化,同时需要配置 compact:true;
  29. stringArray: true, //删除字符串文字并将它们放在一个特殊的数组中
  30. stringArrayEncoding: ['base64'],
  31. stringArrayThreshold: 0.75,
  32. transformObjectKeys: false,
  33. unicodeEscapeSequence: false, //允许启用/禁用字符串转换为unicode转义序列。Unicode转义序列大大增加了代码大小,并且可以轻松地将字符串恢复为原始视图。建议仅对小型源代码启用此选项。
  34. }
  35. const buildConfig = {
  36. entryPoints: ['src/DC.js'],
  37. bundle: true,
  38. color: true,
  39. legalComments: `inline`,
  40. logLimit: 0,
  41. target: `es2019`,
  42. minify: false,
  43. sourcemap: false,
  44. write: true,
  45. logLevel: 'info',
  46. plugins: [
  47. inlineImage({
  48. limit: -1,
  49. }),
  50. glsl(),
  51. sassPlugin(),
  52. ],
  53. }
  54. function getTime() {
  55. let now = new Date()
  56. let m = now.getMonth() + 1
  57. m = m < 10 ? '0' + m : m
  58. let d = now.getDate()
  59. d = d < 10 ? '0' + d : d
  60. return `${now.getFullYear()}-${m}-${d}`
  61. }
  62. async function buildCSS(options) {
  63. await esbuild.build({
  64. ...buildConfig,
  65. minify: options.minify,
  66. entryPoints: ['src/themes/index.scss'],
  67. outfile: path.join('dist', 'dc.min.css'),
  68. })
  69. }
  70. async function buildModules(options) {
  71. const dcPath = path.join('src', 'DC.js')
  72. const content = await fse.readFile(path.join('src', 'index.js'), 'utf8')
  73. await fse.ensureFile(dcPath)
  74. const exportVersion = `export const VERSION = '${packageJson.version}'`
  75. const cmdOut_content = await fse.readFile(
  76. path.join('src', 'copyright', 'cmdOut.js'),
  77. 'utf8'
  78. )
  79. const cmdOutFunction = `
  80. function __cmdOut() {
  81. ${cmdOut_content
  82. .replace('{{__VERSION__}}', packageJson.version)
  83. .replace('{{__TIME__}}', getTime())
  84. .replace(
  85. '{{__ENGINE_VERSION__}}',
  86. c_packageJson.devDependencies['@cesium/engine'].replace('^', '')
  87. )
  88. .replace('{{__AUTHOR__}}', packageJson.author)
  89. .replace('{{__HOME_PAGE__}}', packageJson.homepage)
  90. .replace('{{__REPOSITORY__}}', packageJson.repository)}
  91. }`
  92. const importNamespace = `
  93. import {Cesium , Supercluster } from '@dvgis/dc-common'
  94. `
  95. const exportNamespace = `
  96. export const __namespace = {
  97. Cesium : Cesium,
  98. Supercluster: Supercluster
  99. }
  100. `
  101. // Build IIFE
  102. if (options.iife) {
  103. await fse.outputFile(
  104. dcPath,
  105. `
  106. ${content}
  107. ${cmdOutFunction}
  108. ${exportVersion}
  109. `,
  110. {
  111. encoding: 'utf8',
  112. }
  113. )
  114. await esbuild.build({
  115. ...buildConfig,
  116. format: 'iife',
  117. globalName: 'DC',
  118. outfile: path.join('dist', 'modules-iife.js'),
  119. })
  120. }
  121. // Build Node、
  122. if (options.node) {
  123. await fse.outputFile(
  124. dcPath,
  125. `
  126. ${importNamespace}
  127. ${content}
  128. ${exportVersion}
  129. ${exportNamespace}
  130. ${cmdOutFunction}
  131. `,
  132. {
  133. encoding: 'utf8',
  134. }
  135. )
  136. await esbuild.build({
  137. ...buildConfig,
  138. format: 'esm',
  139. platform: 'node',
  140. define: {
  141. TransformStream: 'null',
  142. },
  143. external: ['@dvgis/dc-common'],
  144. outfile: path.join('dist', 'index.js'),
  145. })
  146. }
  147. // remove DC.js
  148. await fse.remove(dcPath)
  149. }
  150. async function combineJs(options) {
  151. // combine for iife
  152. if (options.iife) {
  153. if (options.obfuscate) {
  154. await gulp
  155. .src('dist/modules-iife.js')
  156. .pipe(javascriptObfuscator(obfuscatorConfig))
  157. .pipe(gulp.src(path.join(dc_common_path, 'dist', '__namespace.js')))
  158. .pipe(concat('dc.min.js'))
  159. .pipe(gulp.dest('dist'))
  160. .on('end', () => {
  161. addCopyright(options)
  162. deleteTempFile()
  163. })
  164. } else {
  165. await gulp
  166. .src([
  167. 'dist/modules-iife.js',
  168. path.join(dc_common_path, 'dist', '__namespace.js'),
  169. ])
  170. .pipe(concat('dc.min.js'))
  171. .pipe(gulp.dest('dist'))
  172. .on('end', () => {
  173. addCopyright(options)
  174. deleteTempFile()
  175. })
  176. }
  177. }
  178. // combine for node
  179. if (options.node && options.obfuscate) {
  180. await gulp
  181. .src('dist/index.js')
  182. .pipe(
  183. javascriptObfuscator({
  184. ...obfuscatorConfig,
  185. target: 'browser-no-eval',
  186. })
  187. )
  188. .pipe(gulp.dest('dist'))
  189. .on('end', () => {
  190. addCopyright(options)
  191. })
  192. }
  193. }
  194. async function copyAssets() {
  195. await fse.emptyDir('dist/resources')
  196. await gulp
  197. .src(dc_common_path + '/dist/resources/**', { nodir: true })
  198. .pipe(gulp.dest('dist/resources'))
  199. }
  200. async function addCopyright(options) {
  201. let header = await fse.readFile(
  202. path.join('src', 'copyright', 'header.js'),
  203. 'utf8'
  204. )
  205. header = header
  206. .replace('{{__VERSION__}}', packageJson.version)
  207. .replace('{{__AUTHOR__}}', packageJson.author)
  208. .replace('{{__REPOSITORY__}}', packageJson.repository)
  209. if (options.iife) {
  210. let filePath = path.join('dist', 'dc.min.js')
  211. const content = await fse.readFile(filePath, 'utf8')
  212. await fse.outputFile(filePath, `${header}${content}`, { encoding: 'utf8' })
  213. }
  214. if (options.node) {
  215. let filePath = path.join('dist', 'index.js')
  216. const content = await fse.readFile(filePath, 'utf8')
  217. await fse.outputFile(filePath, `${header}${content}`, { encoding: 'utf8' })
  218. }
  219. }
  220. async function deleteTempFile() {
  221. await gulp.src(['dist/modules-iife.js'], { read: false }).pipe(clean())
  222. }
  223. async function regenerate(option, content) {
  224. await fse.remove('dist/dc.min.js')
  225. await fse.remove('dist/dc.min.css')
  226. await buildModules(option)
  227. await combineJs(option)
  228. await buildCSS(option)
  229. }
  230. export const server = gulp.series(startServer)
  231. export const dev = gulp.series(
  232. () => copyAssets(),
  233. () => {
  234. shell.echo(chalk.yellow('============= start dev =============='))
  235. const watcher = gulp.watch('src', {
  236. persistent: true,
  237. awaitWriteFinish: {
  238. stabilityThreshold: 1000,
  239. pollInterval: 100,
  240. },
  241. })
  242. watcher
  243. .on('ready', async () => {
  244. await regenerate({ iife: true })
  245. await startServer()
  246. })
  247. .on('change', async () => {
  248. let now = new Date().getTime()
  249. await regenerate({ iife: true })
  250. shell.echo(
  251. chalk.green(`regenerate lib takes ${new Date().getTime() - now} ms`)
  252. )
  253. })
  254. return watcher
  255. }
  256. )
  257. export const buildIIFE = gulp.series(
  258. () => buildModules({ iife: true }),
  259. () => combineJs({ iife: true }),
  260. () => buildCSS({ minify: true }),
  261. copyAssets
  262. )
  263. export const buildNode = gulp.series(
  264. () => buildModules({ node: true }),
  265. () => combineJs({ node: true }),
  266. () => buildCSS({ minify: true }),
  267. copyAssets
  268. )
  269. export const build = gulp.series(
  270. () => buildModules({ iife: true }),
  271. () => combineJs({ iife: true }),
  272. () => buildModules({ node: true }),
  273. () => combineJs({ node: true }),
  274. () => buildCSS({ minify: true }),
  275. copyAssets
  276. )
  277. export const buildRelease = gulp.series(
  278. () => buildModules({ iife: true }),
  279. () => combineJs({ iife: true, obfuscate: true }),
  280. () => buildModules({ node: true }),
  281. () => combineJs({ node: true, obfuscate: true }),
  282. () => buildCSS({ minify: true }),
  283. copyAssets
  284. )