探究Laya關於TypeScript多個版本的編譯問題

-前言-

隨着Laya版本迭代,現在已經到了2.x,每個版本除了修復固定的bug,也增加了很多特性。我們單獨看看Laya對於項目工程的編譯也不斷進行的演變。接下來就從1.x到2.x看看Laya對於編譯的變化。

-正文-

1.x編譯方式

Laya1.x還沒有引入gulp工程化管理工具。而是直接使用Vs Code相關配置來運行項目。其中包括兩個配置。tasks.json與launch.json,tasks.json是在launch.json之前執行的配置文件。

Laya中TypeScript項目就是在tasks.json中對於TypeScript進行編譯的。

//tasks.json
{
"version":"0.1.0",
"command":"tsc",
"isShellCommand":true,
"args":["-p",".","--outDir","bin/js"],
"showOutput":"silent",
"problemMatcher":"$tsc"
}

tasks.json運行tsc命令,tsc是編譯TypeScript命令,當編譯TypeScript的時候會去讀取項目根目錄讀取tsconfig.json文件,這個文件是關於TypeScript編譯的配置文件。關於tsconfig的詳細配置:https://www.tslang.cn/docs/handbook/tsconfig-json.html

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "sourceMap": true
  },
  "exclude": [
    "node_modules"
  ]
}

當我們運行項目的時候會將TS文件編譯成es5格式js文件。

優缺點

儘快1.x項目這樣配置可以滿足我們的項目開發,優點也是很明顯,配置很簡單沒有模塊關聯性,只要安裝了TypeScript就可以運行項目,並且TS到JS編譯是很快的過程,當我們修改了代碼也能很快進行調試。但是缺點也很明顯,首先我們看看項目index.html文件。

從這部分截圖看到,一個html文件中會把我們項目中運用到的js文件全部引入,這個截圖只是一小部分,隨着項目越大,代碼量越多,引入的JS文件會更加多。TypeScript天然符合面向對象編程思想,我們在編寫ts文件的時候基本都是一個類一個文件,包括框架、功能這個js文件數量是不可估量的。大量細小文件會帶來大量http請求,對於Laya這個追求性能的引擎怎麼能容忍這種問題出現。另外這種引入js的方式是需要注意js引入順序的,稍不注意就會造成報錯。因此一種模塊化的引入方式勢在必行。接下來讓我看看2.x的編譯方式。

2.3.0之前

Laya到了2.x時代已經就開始引入gulp工程自動化工具了。這個時候我們依然除了TypeScript不需要安裝任何node模塊即可運行項目,因爲當我們下載Laya的時候所有需要用到的模塊已經放到了Laya的安裝包內中了。目前Laya2.x的編譯方式已經出現了兩種方式。首先我們來看看2.x初期版本的編譯方式。

這個版本主要使用browserify這個模塊編譯ts,當然也會用到tsify,vinyl-source-stream等插件,用戶還可以用watchify監聽文件變更進行時時編譯。tsify主要用於訪問TypeScript編譯器,vinyl-source-stream用於將browserify輸出成gulp能夠解析的格式vinyl。另外諸如uglify等插件功能都可以在管道中使用。

//省略模塊引入代碼

//使用browserify,轉換ts到js,並輸出到bin/js目錄
gulp.task("default", function () {
	return browserify({
		basedir: workSpaceDir,
		//是否開啓調試,開啓後會生成jsmap,方便調試ts源碼,但會影響編譯速度
		debug: true,
		entries: ['src/Main.ts'],
		cache: {},
		packageCache: {}
	})
		//使用tsify插件編譯ts
		.plugin(tsify)
		.bundle()
		//使用source把輸出文件命名爲bundle.js
		.pipe(source('bundle.js'))
		//把bundle.js複製到bin/js目錄
		.pipe(gulp.dest(workSpaceDir + "/bin/js"));
});

通過這種自動化的過程,我們最終可以得到一個bundle.js文件,這個js文件整合了我們所有項目代碼,解決了我上面說到的問題。程序運行的時候首先加載index.html並執行,接着拉取index.js並執行,index裏面會去拉取我們項目所依賴的庫文件以及我們自己的項目文件。

//index.js
//庫文件隨着版本不同有所不同

//-----libs-begin-----
loadLib("libs/laya.core.js")
loadLib("libs/laya.webgl.js")
loadLib("libs/laya.ui.js")
loadLib("libs/laya.physics.js")
//-----libs-end-------
loadLib("js/bundle.js");

以上做法按理說應該沒有問題了,所有文件都打包到了bundle.js中了,不過當我們的項目越來越大還是會出問題,每當我們運行項目的時候都會走一次gulp流程,編譯打包整個流程下來隨着bundle.js越大時間會越慢。可能我們只需要修改一行代碼馬上調試,編譯就有30s,這對於H5項目是無法容忍的,就因爲我們使用TS寫代碼就受這種待遇麼。接下來看看2.3.0版本中Laya對於編譯的優化。

2.3.0版本

到了2.3.0版本,官方優化了發佈壓縮JS參數。首先來看看新版Laya的發佈流程。

//省略模塊引入代碼

gulp.task("compile", prevTasks, function () {
	// 發佈時調用編譯功能,判斷是否點擊了編譯選項
	if (global.publish && !global.config.compile) {
		return;
	} else if (global.publish && global.config.compile) {
		// 發佈時調用編譯,workSpaceDir使用publish.js裏的變量
		workSpaceDir = global.workSpaceDir;
	}

	return rollup.rollup({
		input: workSpaceDir + '/src/Main.ts',
		treeshake: true,//建議忽略
		plugins: [
			typescript({
				check: false, //Set to false to avoid doing any diagnostic checks on the code                
				//刪除註釋
				tsconfigOverride:{compilerOptions:{removeComments: true}}
			}),
            //shader文件
			glsl({
				// By default, everything gets included
				include: /.*(.glsl|.vs|.fs)$/,
				sourceMap: false,
				compress:false
			}),
			/*terser({
				output: {
				},
				numWorkers:1,//Amount of workers to spawn. Defaults to the number of CPUs minus 1
				sourcemap: false
			})*/        
		]
	}).then(bundle => {
		return bundle.write({
			file: workSpaceDir + '/bin/js/bundle.js',
			format: 'iife',//編譯成立即調用函數表達式
			name: 'laya',
			sourcemap: true
		});
	});
});

這個版本的Laya使用到了rollup.js這個模塊打包器插件。這個工具默認只支持es6語法代碼,如果需要支持commonJS需要引入rollup-plugin-commonjs模塊,不過這個版本的Laya已經更改爲es6語法代碼庫了,如果需要向下兼容需要修改編譯文件。使用了rollup-plugin-typescript2對於TypeScript進行編譯,當編譯的時候會生成cache文件,編譯時長變得更短。另外當treeshake設置爲true的時候會靜態分析我們的代碼,並排除任何未實際使用的內容。編譯的時候還會計算循環引用,方便我們檢查代碼的正確性。

這個版本不光編譯速度所有提升,另外增加了代碼檢查的等功能,讓我們能在本地調試階段就注意到一些代碼上的潛在問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章