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.

gulpfile.js 10.0KB

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