App Build Scripts
http://ionicframework.com/docs/v2/resources/app-scripts/
Ionic
使用了TypeScript
和Sass
代码。这些代码需要转换为对浏览器友好的代码,所以需要一个build
过程。@ionic/app-scripts
是一个创建简单的或可以高度自定义的build
过程的配置方式。
它是如何工作的?
Ionic
应用使用ionic serve
和ionic run
命令来开发。这两个命令需要把代码进行编译,组合到一个文件里。
当ionic serve
或ionic run
被调用的时候,实际上是调用了NPM Script
,这些脚本调用了@ionic/app-scripts
来执行这些build
过程。
为什么使用App Script?
大多数应用使用相似的build
进程。我们觉得让用户把时间花在build
过程中更好,而不是花在给自己的App拼凑build
脚本上。我们认为大多数用户都需要这样的build
过程。
那Gulp呢?
之前Ionic
曾经使用gulp
作为build
工具。但是过去几年来,gulp
的开发越来越少,并且被否决的警告越来越多。为了充分利用标准并且免费的NPM Script
,我们减少了对gulp
的依赖并且简化了开发体验。
注意,开发者如果想继续使用gulp
的话也是可以的。我们认为NPM Script
是一种更好的方式,但并不禁止继续使用gulp
。
提供了什么脚本?
@ionic/app-scripts
提供了以下脚本:
- build:
build
调用@ionic/app-scripts
来编译TypeScript
,sass
,打包JavaScript
文件等等。 - bundle:
bundle
使用Rollup.js
来把很多小的JavaScript
文件打包成一个单独的高性能的JavaScript
文件。 - clean:
clean
将会删除所有build
过程产生的文件,一般是删除www
目录下的文件。 - cleancss:
cleancss
使用CleanCSS
来压缩css
文件,可以让css
文件体积更小,加载更快。 - closure:
closure
使用Google’s Closure Compiler
来压缩JavaScript
文件,减小体积提高加载速度。 - copy:
copy
从www
目录里拷贝文件。 - lint:
lint
对TypeScript
源码运行TSLint
。需要在项目根目录下存在tslint.json
文件。 - minify:
minify
对JavaScript
(如果uglify
或closure
可用的话)和css
(cleancss
)运行压缩任务。 - ngc:
ngc
调用Angular Ahead-of-time compiler
来创建高性能的应用,即以AoT
模式编译。 - sass:
sass
遍历应用目录寻找scss
文件并且将它们打包到一个css
文件里。 - template:
template
用来把Angular
模板转换成inline-templates
,使应用载入更快。 - transpile:
transpile
把TypeScript
转换成JavaScript
代码。 - tsc:
tsc
调用TypeScript
编译器。 - uglifyjs:
uglifyjs
用来把JavaScript
最小化,运行更快。 - watch:
watch
创建一个很小的快速的build进程,用于开发过程中。
提供自定义配置
@ionic/app-scripts
提供的默认配置覆盖了大多数开发场景。然而如果开发者需要自定义build
进程运行的配置,可以这样做。
最简单的配置@ionic/app-scripts
的方式是使用package.json
文件中的config
选项。
在package.json
文件中添加一个config
入口。开发者可以提供他们自己的配置文件,比如minification
(closure
编译,uglify2
),和bundling
(rollup
)。
看下面这个明确的自定义文件的例子:
"config": {
...
"ionic_rollup": "./config/rollup.config.js",
"ionic_cleancss": "./config/cleancss.config.js",
...
},
上面这个例子里,从配置文件路径提供了rollup和cleancss的自定义配置。
下面的config值用来映射到任务的配置文件:
Config File | NPM Config Property |
---|---|
CleanCss | ionic_cleancss |
Closure Compiler | ionic_closure |
Copy | ionic_copy |
NGC | ionic_ngc |
Rollup | ionic_rollup |
Sass | ionic_sass |
TSLint | ionic_tslint |
UglifyJS | ionic_uglifyjs |
默认配置是学习如何自定义选项的好例子。
Command line flags
也能够用来提供自定义配置。
自定义项目结构
在大多数情况下,Ionic
提供的默认项目结构可以很好的工作。然而如果开发者要修改项目结构来适应具体的场景,也可以这样做。
像上面提到的一样,通过package.json
中的config
选项,开发者可以指定他们的自定义项目结构。
Config Values | NPM Config Property | Defaults |
---|---|---|
root directory | ionic_root_dir |
process.cwd() |
tmp directory | ionic_tmp_dir |
.tmp |
src directory | ionic_src_dir |
src |
www directory | ionic_www_dir |
www |
build directory | ionic_build_dir |
build |
Ionic环境变量
IONIC_ENV
这个环境变量用于决定build
过程是使用development
模式还是production
模式。这个变量可以这样访问:
if (process.env.IONIC_ENV === 'prod') {
console.log('we got a production buildp');
} else {
console.log('we got a development build');
}
任务细节
Bundle
Ionic
使用Rollup
根据来把不同的JavaScript
文件合并成一个文件。这个过程一般叫做打包。
第三方Module
导出的错误
当在代码中使用第三方库的时候,有时Rollup
需要这个库相关的信息。大多数情况下会工作正常。极少的情况下有些库不知道如何导出数据,我们需要告诉Rollup
什么该被导出。这个过程被称作named Export
。
如果遇到了类似下面的错误信息:
bundle failed: Module myApp/node_modules/js-extend/extend.js does not export extend (imported by myApp/node_modules/pouchdb/lib/index-browser.es.js)
最好的办法是根据上面的步骤创建一个自定义的Rollup
配置文件。需要打开package.json
文件,如果config
节点不存在的话,创建一个config
节点,添加ionic_rollup
值:
"config": {
"ionic_rollup": "./scripts/rollup.config.js"
}
自定义的rollup
配置文件会放置在Ionic
应用根目录下的scripts
目录里。这个例子里这个文件名为rollup.config.js
。
填写Rollup
配置最简单的方式是修改一个已存在的Rollup
配置文件。打开node_modules/@ionic/app-scripts/config/rollup.config.js
文件复制并粘贴其中的代码到scripts/rollup.config.js
中。
现在配置文件的格式正确了,继续来修复上面的错误。在这个例子里,我们试图安装一个超级酷的库pouchdb
。从错误信息可以看出,pouchdb
的lib/index-browser.es.js
文件试图从js-extend
库引入extend
,但报错了。
这个错误意味着Rollup
不知道js-extend
导出了任何名为extend
的东西。解决方案是我们需要告诉Rollup
,js-extend
确实导出了extend
。
这是Rollup
默认的设置:
plugins: [
builtins(),
commonjs(),
nodeResolve({
...
}),
globals(),
json()
]
在Rollup
配置里,我们要找到commonjs
插件,添加一个namedExports
的入口。
commonjs({
namedExports: {
// pouchdb
'node_modules/js-extend/extend.js': ['extend']
}),
我们继续分析namedExport
。
我们的错误看起来是这样的:
bundle failed: Module myApp/node_modules/js-extend/extend.js does not export extend (imported by myApp/node_modules/pouchdb/lib/index-browser.es.js)
错误信息提到了myApp/node_modules/js-extend/extend.js
,还提到了一个名为extend
的导出。
在namedExport
入口,我们不再使用myApp
,但是包含其他的路径作为入口的键。入口的值是一个string
的数组,这个例子里只有一个extend
的入口。
提供namedExports
能够解决大多数的第三方库的问题。
严格模式
Ionic
应用(或任何使用现代JavaScript
的应用)默认采用strict mode
。大多数情况下开发者不需要关心这些。如果一个第三方库没有采用strict mode
支持,在Rollup
配置里禁止strict mode
可以解决。一个流行的库Firebase
需要把strictMode
设置为false
。
使用脚本标签包含
如果还有其他的错误导致无法打包,那就将脚本用<script>
标签引入进来。这是过去二十年来一直使用的方式,现在也可以继续使用。
为了在Ionic
的Page
或Component
中使用一个库,给其一个声明并创建一个变量。例如jQuery
的例子:
declare const jQuery:any;
当jQuery
被浏览器载入的时候,可以通过window.jQuery
来使用它。在上面的例子里,我们把jQuery
映射到了window.jQuery
对象。这样jQuery
就可以无需其他工作就能在TypeScript
中使用了。