Cesium开发工具篇 | 06Cesium源码编译打包

在介绍Cesium源码编译打包之前,先简单的介绍下目前前端工程中一些常用的打包工具,方便后面内容的理解。

前端常用的打包库

(1)gulp打包
gulp是用代码方式来写打包脚本,并且代码采用流式的写法,简单说,gulp是基于 nodejs 的 steam 流打包。它只抽象出了gulp.src,gulp.pipe,gulp.dest,gulp.watch 接口,运用相当简单,更易于学习和使用。Cesium就是利用gulp进行打包的。

(2)webpack打包
webpack是模块化管理工具和打包工具。通过 loader 的转换,任何形式的资源都可以视作模块,比如 CommonJs 模块、AMD 模块、ES6 模块、CSS、图片等。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。它定位是模块打包器,而 Gulp属于构建工具。Webpack 可以代替 Gulp 的一些功能,但不是一个职能的工具,可以配合使用。
webpack是目前最强大的打包工具,非常适合单页面应用程序(SPA)的打包,比如Vue工程、React工程。

(3)rollup打包
rollup是下一代 ES6 模块化工具,最大的亮点是利用 ES6 模块设计,按需打包,利用 tree-shaking生成更简洁、更简单的代码,非常适合前端类库的打包。比如,目前主流的前端JS库Vue、React都是利用rollup打包的。

Cesium打包

在执行打包命令之前,我们需要安装配置Node.js环境,环境配置可参考Cesium开发入门篇 | Cesium开发环境搭建及第一个示例相关内容,这里就不再次详细说明了。环境配置好之后,在某个文件资源目录下打开git命令窗口,输入git clone https://github.com/CesiumGS/cesium.git,拉取Cesium源码。成功后,进入cesium文件目录,执行yarn命令,系统会自动安装各种依赖的包,等待安装完成即可。
安装过程中,我们看一下package.json文件,所有的基于nodeJS创建的前端工程都会有一个package.json文件(创建工程时自动生成的),该文件记录了前端工程的名称、版本、描述、作者、开发环境依赖包(devDependencies)、生产环境依赖包(dependencies)、执行命令说明(scripts)等。我们看下配置文件中有关gulp的命令,如下所示:

"scripts": {
    "convertToModules": "gulp convertToModules",
    "start": "node server.cjs",
    "startPublic": "node server.cjs --public",
    "build": "gulp build",
    "build-watch": "gulp build-watch",
    "build-ts": "gulp build-ts",
    "buildApps": "gulp buildApps",
    "clean": "gulp clean",
    "cloc": "gulp cloc",
    "combine": "gulp combine",
    "combineRelease": "gulp combineRelease",
    "coverage": "gulp coverage",
    "generateDocumentation": "gulp generateDocumentation",
    "generateDocumentation-watch": "gulp generateDocumentation-watch",
    "eslint": "eslint \"./**/*.js\" \"./**/*.cjs\" \"./**/*.html\" --cache --quiet",
    "makeZipFile": "gulp makeZipFile",
    "minify": "gulp minify",
    "minifyRelease": "gulp minifyRelease",
    "release": "gulp release",
    "build-specs": "gulp build-specs",
    "test": "gulp test",
    "test-all": "gulp test --all",
    "test-webgl": "gulp test --include WebGL",
    "test-non-webgl": "gulp test --exclude WebGL",
    "test-webgl-validation": "gulp test --webglValidation",
    "test-webgl-stub": "gulp test --webglStub",
    "test-release": "gulp test --release",
    "deploy-s3": "gulp deploy-s3",
    "deploy-status": "gulp deploy-status",
    "deploy-set-version": "gulp deploy-set-version",
    "prettier": "prettier --write \"**/*\"",
    "prettier-check": "prettier --check \"**/*\"",
    "pretty-quick": "pretty-quick"
  }

这些命令在gulpfile.cjs文件(gulp任务主文件)中都能找到对应的task,task分同步和异步两种,异步的task一般都是通过Promise实现的。废话不多说了,scripts给我们提供了这么多的命令,我们看一下Cesium最终的打包文件是通过哪个命令实现的。观察仔细的童鞋,可能早就发现了,就是release这个命令,在cesium目录下执行 yarn release,结果在Builid文件夹下面生成了如下文件:


image.png

主要包括压缩(Cesium)和未压缩(CesiumUnmimified)的库文件、API参考文档(通过jsdoc实现)三类文件,如果你想在调试的时候查看cesium源码,请引用未压缩的库文件。
我们看一下执行yarn release 命令,中间都经历了什么。如下图所示:


gulp.task(
  "release",
  gulp.series(
    "build",
    "build-ts",
    combine,
    minifyRelease,
    generateDocumentation
  )
);

基本上分了三个部分,
(1)打包前的准备工作:build、build-ts、combine

gulp.task("build", function () {
  mkdirp.sync("Build");
  fs.writeFileSync(
    "Build/package.json",
    JSON.stringify({
      type: "commonjs",
    }),
    "utf8"
  );
  glslToJavaScript(minifyShaders, "Build/minifyShaders.state");
  createCesiumJs();
  createSpecList();
  createJsHintOptions();
  return Promise.join(createWorkers(), createGalleryList());
});
gulp.task("build-ts", function () {
  createTypeScriptDefinitions();
  return Promise.resolve();
});

创建Build文件夹及Cesium文件夹 => 将glsl文件转为js形式 => createCesiumJs方法,遍历Source中所有js脚本,将所有Object记录到Source/Cesium.js => 范例,单元测试模块等。

function combine() {
  const outputDirectory = path.join("Build", "CesiumUnminified");
  return combineJavaScript({
    removePragmas: false,
    optimizer: "none",
    outputDirectory: outputDirectory,
  });
}

gulp.task("combine", gulp.series("build", combine));

在Build文件夹下创建用于保存未压缩cesium库文件的文件夹CesiumUnminified。combineJavaScript 方法稍后再详细讲解。

(2)minifyRelease

function minifyRelease() {
  return combineJavaScript({
    removePragmas: true,
    optimizer: "uglify2",
    outputDirectory: path.join("Build", "Cesium"),
  });
}

gulp.task("minifyRelease", gulp.series("build", minifyRelease));

function combineJavaScript(options) {
  const optimizer = options.optimizer;
  const outputDirectory = options.outputDirectory;
  const removePragmas = options.removePragmas;

  const combineOutput = path.join("Build", "combineOutput", optimizer);

  const promise = Promise.join(
    combineCesium(!removePragmas, optimizer, combineOutput),
    combineWorkers(!removePragmas, optimizer, combineOutput),
    minifyModules(outputDirectory)
  );

  return promise.then(function () {
    const promises = [];

    //copy to build folder with copyright header added at the top
    let stream = gulp
      .src([combineOutput + "/**"])
      .pipe(gulp.dest(outputDirectory));

    promises.push(streamToPromise(stream));

    const everythingElse = ["Source/**", "!**/*.js", "!**/*.glsl"];
    if (optimizer === "uglify2") {
      promises.push(minifyCSS(outputDirectory));
      everythingElse.push("!**/*.css");
    }

    stream = gulp
      .src(everythingElse, { nodir: true })
      .pipe(gulp.dest(outputDirectory));
    promises.push(streamToPromise(stream));

    return Promise.all(promises).then(function () {
      rimraf.sync(combineOutput);
    });
  });
}

combineJavaScript做了两件事情,打包Cesium和Workers脚本。Gulp根据指令的不同,比如minify下采用uglify2优化,而combine对应的参数为none,生成路径为CesiumUnminified。

(3)generateDocumentation

function generateDocumentation() {
  child_process.execSync("npx jsdoc --configure Tools/jsdoc/conf.json", {
    stdio: "inherit",
    env: Object.assign({}, process.env, { CESIUM_VERSION: version }),
  });

  const stream = gulp
    .src("Documentation/Images/**")
    .pipe(gulp.dest("Build/Documentation/Images"));

  return streamToPromise(stream);
}
gulp.task("generateDocumentation", generateDocumentation);

API参考文档就是基于 generateDocumentation 命令自动生成的,引用了jsdoc文档生成库,通过解析jsdpoc配置文件Tools/jsdoc/conf.json而生成的。

本文只简单介绍了打包流程中的部分代码,感兴趣的同学可以查看cesium源码中的gulpfile.cjs文件内容。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,841评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,415评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,904评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,051评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,055评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,255评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,729评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,377评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,517评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,420评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,467评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,144评论 3 317
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,735评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,812评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,029评论 1 256
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,528评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,126评论 2 341

推荐阅读更多精彩内容