# tua

tua是一个基于webpack的工作流，集成了下一代开发语言，提供语言层面的支持。
它封装了webpack的复杂度，集成了webpack使用的最佳实践。
让开发者更加关注业务，而非复杂的配置和工具选择。

## 1. 快速开始

1. 通过 npm 或 yarn 安装tua

```shell
npm i -g tua
yarn global add tua
```

注意，使用 yarn，需要配置环境变量。否则，全局命令不生效。

2. 在项目根目录下执行初始化命令

```shell
tua new
```

此命令会在项目根目录下生成  **tua** 的配置文件`.tuarc`，以及一个简单示例。并自动下载安装所需npm依赖。
可以根据项目需要修改配置。见 `tua` 配置说明。

3. 开始调试

```shell
tua start
```

启动服务器。

4. 打开页面

	* 在浏览器中输入 [http://localhost:9527/hindex.html](http://localhost:9527/hindex.html)  [http://localhost:9527/sports.html](http://localhost:9527/helloexpress)查看页面

	* 在浏览器中输入 [http://localhost:9527/helloexpress](http://localhost:9527/helloexpress) 查看直出页面

## 2. 命令行接口(CLI)
### 2.1. 初始化生成项目模板
```shell
tua new
tua n
```
执行后，会在执行目录下生成项目模板。

#### 2.1.1. 模板结构
```
+ app          代码源文件
    + lib        公共代码库
        utils.js   公用的js
    a.js			 异步模块
    index.js      入口
    index.html    html模板
    index.scss    sass文件
    sports.html   html模板
    sports.js     入口
+ server
    boot.js    适配服务端框架的直出启动文件（比如tsw）
    index.js   直出入口
    sports.js  直出入口
+ test         测试文件
    add.js     测试文件
package.json   包配置文件
.editorconfig  编辑器配置文件
.gitattributes Git配置
.gitignore     Git忽略提交规则
.tuarc         tua配置文件
README.md      项目说明文件
```
#### 2.1.2. 自动下载
在生成 package.json 后，npm 包的自动安装会启动。优先使用 yarn 安装，如果没有安装则会选择 npm。

### 2.2. 生成DLL文件 Deprecated
DLL是套用window中动态链接库的概念。
DLL的使用，是webpack优化的一部分。
把变化不频繁的部分（如 vue react 的库文件等）打到DLL包中，可以提升调试阶段和发布阶段的编译速度，节省时间，提升效率。
如需了解详情，请自行google，这里不再累述。

```shell
tua dll
```
此命令无需手动执行，在使用 `start` 或 `pack` 时，程序会自动检测是否需要生成或更新 DLL 文件。

### 2.3. 启动本地调试服务器
#### 2.3.1.  使用默认框架express
```shell
tua start
```
启动一个 webpack-dev-server(框架是express), 带有热更新。
启动前，会检测是否需要更新 DLL 文件。

#### 2.3.2 使用 koa
默认情况下，webpack-dev-server 提供一个 express 的服务器，tua 额外提供对 koa 的支持，只需在此命令的末尾添加 `-k` 或者 `--koa`,
```shell
tua start --koa
tua start -k
```
以上命令会启动 Koa 服务器。

#### 2.3.3.  给 pages 配置传递参数
pageEntries方法是入口的生成函数，见 3.6
启动本地服务时，在 `start` 后添加字符串，可以当做参数传递给 `pages`方法，用于筛选页面等。

```shell
tua start index
```

### 2.4. 打包
#### 2.4.1. 打包本地使用
```shell
tua pack
```
打包后，资源路径都是本地相对路径，用于本地查看或html和资源部署到同一目录的情况。
打包会同时打包客户端代码和服务端代码，服务端代码入口在 `serverEntry` 配置处设置。见下文详细说明。

#### 2.4.2. 打包服务器使用
```shell
tua pack -t
tua pack --toserver
```
打包后，资源路径指向 .tuarc 中配置的 `serverUrl`， 用于使用 CDN 或者 html 和资源部署到不同路径的情况。

### 2.4.3.  给 pages 配置传递参数
pageEntries方法是入口的生成函数，见 3.6
启动本地服务时，在 `start` 后添加字符串，可以当做参数传递给 `pages`方法，用于筛选页面等。

```shell
tua pack index
```

### 2.5. 启动测试

需安装插件支持：@babel/test

```shell
tua test --stage {stage}
tua test -s {stage}
```
stage的值从 [‘start', 'run', 'stop', 'init', 'completion'] 选择。

集成了 `karma + mocha + chai + sinon` 的测试框架。
需配置 .tuarc 中的 `testbase`，默认是 test 文件夹。

### 2.6. 执行js文件
```shell
tua run filename
```
从目标文件启动，可自行封装start等命令。
此文件中可以调用 tua 的模块，以及 tua 依赖的 npm 包。

### 2.7. 新增模板

需安装插件： @tuax/cli

1. 初始化项目（代理 vue-cli v2 的 init 功能）

```shell
tua init <template-name> <project-name>
```

1. 新增 api

```shell
# 新增 web 端 api
tua add api <api-name>

# 新增小程序端 api
tua add api <api-name> -w
```

2. 新增页面

```shell
# 新增 web 端 page
tua add page <page-name>

# 新增小程序端 page
tua add page <page-name> -w
```

3. 新增组件

```shell
# 新增 web 端 comp
tua add comp <comp-name>

# 新增小程序端 comp
tua add comp <comp-name> -w

# 新增 web 端全局 comp
tua add comp <comp-name> -g

# 新增小程序端全局 comp
tua add comp <comp-name> -g -w
```

### 2.8. 导出默认模板
这个命令将包中的默认模板导出到 `.templates/` 中。

这样通过修改`.templates/` 下的模板文件，即可实现自定义模板功能。

```shell
tua eject
```

### 2.9. 指定模板文件夹
**读取模板的优先级逻辑是：**

1. 首先尝试使用 `tua.config.js` 中的 `templateDir` 字段
2. 接着尝试读取 `.templates/`
3. 最后读取默认模板

### 2.10 生成接口声明命令
这个命令将读取导出的 apis 然后自动生成 `index.d.ts`。

```shell
tua declare [apisPath]
```

* `apisPath` 默认值为 `src/apis/index.js`
* `index.d.ts` 将生成在 `apisPath` 同级目录下

由于使用 `require` 读取导出 apis 对象的文件，所以可能会碰到 `alias` 问题。例如项目中设置了 `@` 作为 `./src/` 的别名。虽然 `@tua-mp/cli` 已内置了一些 `alias`，但你仍然可以自由配置。

在 `tua.config.js` 中的 `alias` 选项会透传给 [babel-plugin-module-resolver](https://github.com/tleunen/babel-plugin-module-resolver)，例如将 `foobar` 指向 './src/foobar' 可以这么配置：

```js
// tua.config.js
module.exports = {
    alias: {
        'foobar': './src/foobar',
    },
}
```

## 3. 配置
tua 的配置文件 `./.tuarc` 在执行初始化命令之后自动在项目的根路径下生成。
.tuarc 是一个正规的 nodejs 模块，暂不支持ES6语法。
以下是每一个配置项的说明。

### 3.1. supportIe{Boolean} deprecated in 0.9.0
打包后的文件是否支持 IE8。默认给出的选项是`false`。
IE8 的支持需要一些特殊的库以及 webpack 插件的支持，当选项为`true`时，工作流会自动调整配置，以适应IE8的要求。
注意： IE8的支持不完全，某些 ES6 的属性慎用。另外，如需搭配 vue 等不支持 IE8 的库，请自行查询如何配置loader和插件以提供兼容。

注： 0.9.0 已经不再支持IE8。

### 3.2. cssEnhance {Array<string, object> | string | object }
css 增强loader，单个loader配置符合 webpack 标准的loader配置

注：需要在项目中安装插件支持 @tuax/plugin-css-preprocessor

#### 3.2.1. 支持的loader
* 内置css loader： sass，postcss，less
* 本地安装的 css loader 需要加上 -loader，如使用本地安装特定版本的 postcss， 可配置成 postcss-loader

#### 3.2.2. 关于 postcss
默认配置中，postcss使用的插件如下：
* postcss-smart-import
* precss
* autoprefixer

配置文件生成规则如下：
1. 自动生成 .postcssrc.js
默认会根据浏览器环境配置 `env` 在项目根目录下生成 **.postcssrc.js**， 此文件使用 tua 包中默认安装的 postcss插件地址，因此每人机器上配置文件不同，不要上传到版本库。

2. 用户自定义配置 postcss.config.js
用户在定义了 postcss.config.js 的情况下，上述配置文件不会自动生成，如果已经生成，请手动删除，以免造成不确定性的bug。

#### 3.2.3. 注意事项
1. 数组对象配置的顺序符合webpack loader加载对象从右向左处理的顺序

### 3.3. ~~ pretty {Boolean | Object} ~~
是否在启动 webpack 时，使用[prettier](https://github.com/prmettier/prettier)自动格式化代码。
如果需要格式化代码，则`pretty`的值应该是 [prettier](https://github.com/prettier/prettier) 的配置。

### 3.4. enableProfile {Boolean}

需要安装插件支持：@tuax/plugin-profile

是否生成profile文件，profile可用于查看生成块的大小等信息。
如果选是，打包完成后，会自动打开集成的profile工具，可方便的查看每个 chunk 的信息。

### 3.5. env {Object}

```js
 /**
     * 定义浏览器环境，babel-preset-env 插件使用的环境
     * browsers {Array<string> | string} 浏览器支持
     *     或者 {
     *              debug: {Array<string> | string}, 浏览器支持
     *              publish: {Array<string> | string} 浏览器支持
     *          }
     * https://github.com/ai/browserslist http://browserl.ist/
     */
    browsers: {
        debug: '',
        publish: ''
    }
```

可分别定义debug阶段和发布阶段打包支持的浏览器环境。
在调试阶段把环境设置成固定的（比如 chrome） 可以加快编译速度，减少等待时间。

### 3.6. pages {Function}
配置项目的入口，重要属性，必须配置。 **路径中注意要统一使用 / , windows 中会使用 \ ，需自行处理**
值需要是一个匿名函数。
```js
/**
 * 生成entries入口的函数，返回数组类型，每个对象都应包括四项, 路径中注意要统一使用斜杠 / ,windows 中会使用 \ ，需自行处理
 * @param param 用于过滤等功能的cli传过来的参数 两个命令可以传递此参数 tua start --param, 或者 tua pack -t toserver --param / tua pack --param
 * @return Object {
 *       index: {
 *           // page 的入口
 *          entry: './src/index',
 *           serverEntry: './src/index.server', //ssr 不能独立于终端的 entry 存在，因此，每一个终端入口 +.server 的方式命名的 js 文件都是此页面的ssr方式的入口
 *           // 模板来源
 *           template: 'src/index.html',
 *           inlineSource: '.css|js$', // embed all javascript and css inline
 *           // 在 dist/index.html 的输出
 *           filename: './hindex.html',
 *           // 当使用 title 选项时，
 *           // template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
 *           title: 'Index Page',
 *           // 在这个页面中包含的块，默认情况下会包含
 *           // 提取出来的通用 common, manifest
 *          chunks: ['common', 'manifest', 'index']
 *       },
 *       // 当使用只有入口的字符串 ${pagename}: ${entry} 格式时，
 *       // serverEntry: ${entry}.server 如果 ${entry} 以 .js 结尾，去掉 .js， 如果没有，为非同构页面
 *       // template: `src/${pagename}.html`  如果找不到，使用 src/default.html 如果还没有，使用 tua 自带默认模板
 *       // filename: ${pagename}.html
 *       sports: './src/sports'
 *   }
 * 支持 html-webpack-plugin 的所有配置，见： https://github.com/jantimon/html-webpack-plugin#user-content-options
 */
pages: function (param) {
    return {
        index: {
            // page 的入口
            entry: './src/index',
            serverEntry: './src/index.server', //ssr 不能独立于终端的 entry 存在，因此，每一个终端入口+.server 的方式命名的 js 文件都是此页面的ssr方式的入口
            // 模板来源
            template: 'src/index.html',
            inlineSource: '.css|js$', // embed all javascript and css inline
            // 在 dist/index.html 的输出
            filename: './hindex.html',
            // 当使用 title 选项时，
            // template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
            title: 'Index Page',
            // 在这个页面中包含的块，默认情况下会包含
            // 提取出来的通用 common, manifest
            chunks: ['common', 'manifest', 'index']
        },
        // 当使用只有入口的字符串 ${pagename}: ${entry} 格式时，
        // serverEntry: ${entry}.server 如果 ${entry} 以 .js 结尾，去掉 .js， 如果没有，为非同构页面
        // template: `src/${pagename}.html`  如果找不到，使用 src/default.html 如果还没有，使用 tua 自带默认模板
        // filename: ${pagename}.html
        sports: './src/sports'
    }
}
```
参数 函数接受一个参数，可以在 `start` 或 `pack` 阶段，用 `--param` 的方式传递过来，常用于优化调试速度，或部分打包上线。默认会打包所有页面。
返回值需要是一组符合上述结构的对象。

### 3.7. html {Object}
html-webpack-plugin 中关于html生成的压缩配置。见:[https://github.com/kangax/html-minifier#options-quick-reference](https://github.com/kangax/html-minifier#options-quick-reference)

### 3.8. testbase {String}
@tuax/test 扩展属性，测试文件路径

### 3.9. dist {String}
打包代码输出的文件夹路径，需要是绝对路径。

### 3.10. ~~src {String}  Deprecated~~
代码source路径，缩小loader的处理范围。
已失效。

### 3.11. assertsLimit {Integer}
大小小于 {assertsLimit}B 的资源，会自动base64到代码中。

### 3.12. serverUrl {String}
执行打包到 toserver 时，静态资源会上传至cdn，此为静态资源文件夹地址。

### 3.13. open {String | Boolean | Object}
是 webpack-dev-server 中 open 和 openPage 的缩写，其中

#### 3.13.1. open 设置为浏览器类型
```js
open : 'google chrome'
```

#### 3.13.2. open设置为布尔值时
```
open : false
```
值 false 时，不自动打开浏览器。
true时，打开当前服务地址

#### 3.13.3. open设置为对象时
```js
open : {
    pathname: 'xxx.html',
    app: 'google chrome'
}
```

执行 `start` 后，启动服务器成功后浏览器打开地址。

 如果 webpack 的 `devServer` 配置和`open`配置同时存在时，以 `open` 的设置为准，`open`不存在时，以`devServer`的配置为准

### 3.14. devServer {Object}
```js
{
    proxy: {
        "/api": {
            target: "http://localhost:3000", //代理的服务器地址
            bypass: function (req, res, proxyOptions) {
                //过滤器
            }
        }
    },
    port: 9527,
    localhost: 'a.com',
    // 匹配一直的参数会追加到url中
    // [
    //    [rule1, param1],
    //    [rule2, param2]
    // ]
    // rule 可以是 String 类型或者正则表达式
    // 优先匹配到的先生效 比如 [[/s/,'?a=bb'],['sports.html':'?b=aa']]， 后面这条永远不会生效
    defaultParams: [
        [],
        []
    ]
}
```

可设置proxy和端口号，以及快捷启动的localhost映射域名
localhost 设置后，在非windows系统中，tua 会自动帮您设置host，并在退出时清理自动设置的host，请根据提示输入管理员密码。

### 3.15. resolve {Object}
```js
{
    /**
     * 别名配置，可以配置短路径和文件
     * eg. "jquery" : require("./lib/jquery")
     */
    alias: {
        // "jquery" : require("./lib/jquery")
    }
}
```
可配置别名，如上例为 jquery 配置了别名。

### 3.16. globalVar {Object}
为某些模块配置全局变量。
如：
```js
{
    $: 'jquery'
}
```

### 3.17. dll {Object}

配置dll块，可配置需要打包成dll的块
如：

```js
{
    chunks: {
        // vendor: ['./src/lib/utils'],
            vendor2: ['./src/lib/utils'],
    },
}
```

### 3.18. ~~serverEntry~~

合并配置到 pages.
serverEntry 应该是一个 Object 类型的值，或者是一个函数，返回 Object 类型的值

```js
serverEntry : {
    index : './server/index'
}
// or
serverEntry : function(params){
    return {
        index : './server/index'
    }
}
```

如果是函数类型，则会在执行时，接受 `tua start` 或 `tua pack` 命令传递过来的参数，可以用于过滤等操作。

#### 3.18.1. 入口

入口模块必须默认是一个方法，支持两种形式，es5的模式

```js
module.exports=function(server){

}
```

或者 es6 模式

```js
export default (server)=>{

}
```

方法需从 server 对象中获取 router 和 app 等用于创建路由和后台直出。

```js
//index.js
module.exports = function (server) {
    const router = server.router;
    const app = server.app;
    //koa example
    router.get('/bbbf', function (ctx) {
        ctx.type = 'text/html';
        let htmlcode = server.mfs('/app/index.html', 'utf-8');
        ctx.body = htmlcode + ' for koa!';
    })
//express example
    router.get('/bbbc', function (req, res, next) {
        let htmlcode = server.mfs('/app/index.html', 'utf-8');
        res.send('for express： ' + htmlcode);
    })
}
```

#### 3.18.2. 入口接收的 server 对象

debug 阶段的 `server`是`webpackDevServer`的实例，常用到的属性和方法如下

```js
{
    app: {koa or express}
    router: {koa-router Object or express router Object}
    mfs: {Function}
}
```

#### 3.18.3. mfs 方法

```js
/**
* 读取html模板的代码
* @param htmlPath 源代码中，html文件的路径
*/
function mfs(htmlPath){}
```

注意，路径需要以 '/' 开头，对应项目根目录。

#### 3.18.4. 使用打包后的服务端文件

打包后，会生成 `dist/server.js`, 此文件中不包含服务器创建部分，因此，使用时，需要根据入口文件中使用到的server的属性，创建相应的对象

以使用`koa`为例，boot.js,

```js
require('source-map-support').install();//支持 sourcemap
const entry = require('./dist/server/index');
const Koa = require('koa');
const Router = require('koa-router');
 // 初始化koa实例
const app =  new Koa(); // eslint-disable-line
const router = new Router();//初始化koa router

app.use(router.routes()).use(router.allowedMethods()); //绑定路由
entry({
    app: new Koa(),
    router: new KoaRouter()
})
```
其中， `source-map-support` 需要在服务端安装npm包。非必须，不需要可删除。

### 3.19. babelrc
```js
/**
 * {
 *    include: [],
 *    presets: {Array<string> | string}
 *    plugins: {Array<string> | string}
 *  }
 */
{ 
    include: [/regs/],
    presets: {Array<string> | string},
    plugins: {Array<string> | string}
}
```
用于扩展 .babelrc，例如，如果需要使用react，需要这么写：
```js
{
    presets: ["react"]
}
```

#### include
默认配置中`babel-loader`编译会排除 `node_modules`，但是内部发布的很多包会直接发布未编译成es5的版本，因此 `node_modules` 中某些部分应该被babel编译。
`include` 是包含正则表达式的数组构成。

#### 版本升级指引
babel7 在tuax中的支持版本始于 0.9.17， 不兼容babel6的配置。

babel7 进行了大量的重构，可先根据 babel 官网进行 babel6 到 babel7 的升级。

升级到 tuax 0.9.17 及以上时，需要修改的点有两个：

* 配置本地需要的运行时库
package.json 中需要配置的 babel 包：

```js
"dependencies": {
    "@babel/runtime": "latest",
    "@babel/runtime-corejs2": "latest"
}
```

* 在 .tuarc 中配置 babel 支持新语言特性的 plugin，比如，装饰器等，插件如下：

```js
    babelrc: {
        // 可以使用以下配置尝试新功能, 注意需要安装后使用
        // plugins:[
        //     "@babel/plugin-proposal-class-properties",
        //     ["@babel/plugin-proposal-decorators", {legacy: true}],
        //     "@babel/plugin-proposal-do-expressions",
        //     "@babel/plugin-proposal-export-default-from",
        //     "@babel/plugin-proposal-export-namespace-from",
        //     "@babel/plugin-proposal-function-bind",
        //     "@babel/plugin-proposal-function-sent",
        //     "@babel/plugin-proposal-json-strings",
        //     "@babel/plugin-proposal-logical-assignment-operators",
        //     "@babel/plugin-proposal-nullish-coalescing-operator",
        //     "@babel/plugin-proposal-numeric-separator",
        //     "@babel/plugin-proposal-optional-chaining",
        //     ["@babel/plugin-proposal-pipeline-operator", { "proposal": "minimal" }],
        //     "@babel/plugin-proposal-throw-expressions",
        // ]
    }
}
```

如果需要使用装饰器，需要在package.json中引入并下载 `@babel/plugin-proposal-decorators`，然后，将 tuax 中对应的插件打开即可使用。

### 3.20 plugins

用于配置 tua 的插件，现在内置拆件有以下几个，安装在项目根目录下后，方可使用

```js
[
    [require(pluginname), pluginOptions]
    require(pluginname) 
]
```
也可以引入自定义插件


#### 3.20.1 插件列表

##### @tuax/cli

扩展 tua 脚手架，可以方便的生成模板以及添加模块等
内置，无需安装

##### @tuax/plugin-babel

babel支持，内置，无需安装

##### @tuax/plugin-test

见testbase
支持测试

##### @tuax/plugin-profile

见 enableProfile
支持打包情况查看

##### @tuax/plugin-imgmin

支持图片压缩

##### @tuax/plugin-css-preprocessor

见 cssEnhance
支持css预处理

#### 3.20.2 自定义插件

实现以下方法即可

```js

/**
 * 扩展命令行
 * @param yargv yargs 对象 见： [yargs](http://yargs.js.org/docs/)
 * @param options 插件配置
 */
module.exports.command = function (yargv, options) {

}

/**
 * 初始化option，设置扩展字段的校验和默认值
 * 扩展 .tuarc 配置
 * 见： [joi](https://github.com/hapijs/joi)
 * @param joi对象
 * @param options 插件配置
 * @return {Object}
 * {
 *     pluginScheme: joi scheme
 *     pluginDefaultOptions: 默认值
 * }
 */
module.exports.options = function (joi, options) {
    return {
        pluginScheme: {

        },
        pluginDefaultOptions: {

        }
    }
}
/**
 * 扩展客户端 webpack 配置
 * @param chainedConfig webpack-chain对象 见： [webpack-chain](https://github.com/neutrinojs/webpack-chain)
 * @param env 当前环境， 包括 DEBUG，PUBLISH，TOSERVER，对应命令执行的三个阶段
 * @param config  .tuarc 配置和默认配置合并后的最终配合
 * @param options 插件配置
 */
module.exports.clientConf = function (chainedConfig, env, config, options) {

}
/**
 * 扩展服务端 webpack 配置
 * @param chainedConfig webpack-chain对象 见： [webpack-chain](https://github.com/neutrinojs/webpack-chain)
 * @param env 当前环境， 包括 DEBUG，PUBLISH，TOSERVER，对应命令执行的三个阶段
 * @param config  .tuarc 配置和默认配置合并后的最终配合
 * @param options 插件配置
 */
module.exports.serverConf = function (chainedConfig, env, config, options) {

}
/**
 * 扩展服务端 webpack 配置
 * @param chainedConfig webpack-chain对象 见： [webpack-chain](https://github.com/neutrinojs/webpack-chain)
 * @param env 当前环境， 包括 DEBUG，PUBLISH，TOSERVER，对应命令执行的三个阶段
 * @param config  .tuarc 配置和默认配置合并后的最终配合
 * @param options 插件配置
 */
module.exports.dllConf = function (chainedConfig, env, config, options) {

}

/**
 * webpack 开始编译前的z准备
 * @param env 当前环境， 包括 DEBUG，PUBLISH，TOSERVER，对应命令执行的三个阶段
 * @param config  .tuarc 配置和默认配置合并后的最终配合
 * @param options 插件配置
 */
module.exports.beforeCompile = function (env, config, options) {

}

/**
 * 扩展项目的package.json, 注入配置
 * @param options 插件配置
 * @return {Object} package.json的配置扩展
 */
module.exports.generate = function (options) {
    return {}
}

```

## 4. 进阶
### 4.1. 直接调用 tua 时的参数传递
**.tuarc** 配置文件中的 **pageEntries** 方法可以接收一个名为 `params` 的参数：
```js
pageEntries: function (params) {
   //params可以用于过滤入口和html文件
   return entryDatas;
}
```
这个参数在过滤入口和页面时会显得尤为有用，它可以通过执行 `start` 或 `pack` 后添加 `--param` 来添加
```shell
tua start --param xxx
tua pack --param xxx
tua pack --param xxx -t toserver
```
#### 4.1.1. 调用配置在 npm scripts 中命令的参数传递
**npm scripts**中可以很方便的配置命令行，可以结合其他命令，方便调用。
比如：
```js
 "scripts": {
    "toserver": "rimraf dist/* .cache-loader/* && tua pack toserver && kcms -c"
  }
```
但，使用这种方式的时候，无法给**pageEntries**方法传递参数。

为了支持 **npm scripts** 中调用**tua**命令时传递参数，需要设置 **npm** 的参数 `--params`：
```shell
npm run toserver --params=xxx
```
这时，.tuarc 中的 pageEntries 方法就会接收到 'xxx'。

#### 4.1.2. 使用 koa 作为服务器
默认在webpack-dev-sever中，使用express作为服务器，但加载koa模块会略显复杂。

`start` 在检测到最后一个参数为 `koa` 时，会启用 `koa` 作为服务器。

```shell
tua start koa

tua start --param xxx -k
```
默认增加了对node端sourcemap的支持，方便定位问题。

### 4.2. 设置目标浏览器环境
#### 4.2.1. 不区分开发阶段的配置
在 .tuarc 的配置文件中， `env.browsers` 可以用来设置目标浏览器。值可以是 `{Array<string> | string}`。
```js
env:{
browsers: {Array<string> | string}
}
```#### 4.2.2. 区分测试和发布阶段的配置
一般，在debug模式下，可以只支持chrome就可以完成开发。
```js
env:{
    browsers: {
         debug: {Array<string> | string},
         publish: {Array<string> | string}
    }
}
```### 4.3. 使用工具中的模块
#### 4.3.1. 获取当前环境
```js
let env = require("@tua/utils/env");
console.log(env.DEBUG);
console.log(env.PUBLISH);
console.log(env.TOSERVER);
```
以上方式可以获取当前是处于 `DEBUG`,`PUBLISH`,`TOSERVER` 的状态，方便自助扩展webpack使用。

#### 4.3.2. 自定义启动文件
执行命令
```shell
tua run -f start.js
```
start.js
```js
let tua = require("@tua");
tua.start();
```
以上代码可以启动 `dev server`。
可用的 tua API，见下面部分。

## 5. API
### 5.1. .DLL(suc, fail)
根据 **tua.js** 中的配置，生成 **dll** 文件。
##### 5.1.1. suc
生成dll文件成功后的回调
##### 5.1.2. fail
生成dll失败后的回调

`suc`和`fail`都是可选参数。

### 5.2. .start(params, callback, spinner)
启动服务器
##### 5.2.1. params
参数，可用于过滤入口
##### 5.2.2. callback
启动服务器成功后的回调
##### 5.2.3. spinner
webpack的devserver启动中，需要此对象展示阶段性信息，不传默认不展示。

三个参数都是可选。

### 5.3. .pack(stat, params, suc, fail)

打包发布项目

##### 5.3.1. stat

PUBLISH TOSERVER 两种选一，不传默认是PUBLISH

##### 5.3.2. params

参数，可用于过滤入口

##### 5.3.3. suc

成功回调

##### 5.3.4. fail

失败后的回调

四个参数都是可选。

## CHANGELOG

### 2019-10-22 v0.10.4

Fix:

* 修复只有非服务端渲染页面的情况下，没有提示url地址的bug

### 2019-10-22 v0.10.3

Fix:

* pack 打包阶段thread-loader创建的子进程中没有经过hack-require导致找不到类似webpack等安装到tua下的模块

### 2019-10-10 v0.10.2

New feature:

* pages 配置，返回的对象属性新增 entryCode， serverEntryCode , 支持配置一段代码为webpack的入口，可用于项目中动态生成入口文件，简化项目配置

### 2019-09-25 v0.10.1

New feature:

* 在debug阶段，sever端也支持编译输出到内存中，减少IO，优化编译速度

### 2019-09-15 v0.10.0

Breaking changes:

* 删除了pageEntries 和 serverEntry，合并到pages
* 删除了 dllChunk，扩展新字段 dll，原dllChunk值可设置为 dll.chunk
* 不再默认支持图片打包，需安装插件支持
* 不再默认支持webpack打包块查看，需安装插件支持
* 不再默认支持css增强，需要本地安装插件支持
* 不再默认支持单元测试，需要本地安装插件支持

New feature:

* 全新的命令行
  * 更加语义化的命令行
  * 新增全新脚手架
  * 无效命令检测
  * 启动执行速度优化
* 新的配置文件 .tuarc
  * 约定大于配置，配置大大简化，0配置即可运行
  * 新增 .tuarc 配置校验
  * 新增webpack链式扩展，chainClientConf，chainServerConf
  * 简化配置，合并了serverEntry 和 pageEntries 为 pages，并提供了方便的根据文件夹生成配置的默认方法
* 新增插件支持
* 优化输出展示
  * webpack bar展示进度
  * 打包成功后，展示可用服务列表
  * 打包后，集中展示所有错误，便于发现问题
  * 新增 devServer.localhost 可配置 localhost 映射地址
  * 支持devServer的新配置 defaultParams，可配置启动时提示url的参数
* 安装包瘦身，安装更快
* 服务端编译支持 HMR
* 优化服务端编译速度，忽略node端不需要处理的类型

Bug fix:

* 新建项目没有 src 文件夹的问题
* babel7.0后 treeshaking 修复
* cache-loader 等缓存位置变化，没有及时清理导致打包不更新
* 开启 MD5 hash 情况下，动态import css问题修复
* 为`babelrc`添加`include`配置，解决`node_modules`中存在未编译成es5模块被引用无法编译的问题。
* 修复ios10中`terser`依赖包`uglify-js`在压缩代码时，当你定义一个与参数同名的for循环迭代变量时，ios10版本Safari会错误地认为这是一个语法错误的问题 
* 修复 htmlplugin 中变量无法被解析问题，使用文件的 watch 代替 raw-loader

### 2019-04-28 v0.9.28

* 修复ios10中`terser`依赖包`uglify-js`在压缩代码时，当你定义一个与参数同名的for循环迭代变量时，ios10版本Safari会错误地认为这是一个语法错误的问题
* 为`babelrc`添加`include`配置，解决`node_modules`中存在未编译成es5模块被引用无法编译的问题。

### 2019-03-20 v0.9.27

* 紧急修复 webpack-dev-middleware@3.6.1 无法启动的问题
* 修复htmlplugin中变量无法被解析问题， 暂时去掉 html 修改触发 hmr 的功能

### 2019-02-26 v0.9.26

* 使用 terser 代替 uglify 压缩
* 去掉.tuarc 中的 src 配置项

### 2019-01-31 v0.9.25

* serverEntry支持动态返回，可根据命令行参数进行入口过滤
* 无效命令会有提示

### 2019-01-22 v0.9.24

* babel-loader 去除默认对node_module的忽略配置。
* 解决了html和直出服务端文件修改无法触发hmr的bug

### 2018-12-06 v0.9.21

* babel-loader 起作用的范围支持数组，对应tuarc中的 src 配置项。

### 2018-12-06 v0.9.20

* open bug fix，把open为对象时的uri属性名改为pathname

### 2018-11-22 v0.9.17

breaking change
* babel7 支持

#### 升级指引
见 3.19

### 2018-11-20 v0.9.16

* 修复直出debug模式下 HMR 的问题

### 2018-11-08 v0.9.15

* devServer配置 https 支持

### 2018-10-17 v0.9.12

* 修复 md5hash 失效的问题

### 2018-10-08 v0.9.11

* 修改在 webpack.config.js文件中直接 require('webpack') 可能引用不到tua中安装的webpack导致错误的问题。
  根据包查找规则，距离近的webpack会被先找到，找不到的才会被tua的requirehack修正到tua中。现在改为强制使用tua中安装的版本，为了可以使不同版本的webpack共存。

### 2018-09-26 v0.9.10

* 更新 postCSS 插件，添加 cssnano 压缩，解决 autoprefixer 添加的前缀被 optimize-css-assets-webpack-plugin 删除的问题

### 2018-09-26 v0.9.5

Breaking changes:
* 简化webpackserver端配置，减少不必要的处理步骤，提升性能。

### 2018-09-23 v0.9.3

Breaking changes:
* 文件名生成使用文件内容的MD5hash，用作永久缓存和客户端文件完整性校验。

### 2018-09-17 v0.9.1

Breaking changes:
* 梳理命令行，重新定义了命令。

### 2018-05-30 v0.8.38

* 更名：属性 pageEntrys 更名为 pageEntries，兼容原方法
* 开放html-webpack-plugin的配置，可直接在pageEntry中使用官方属性配置，详见：https://github.com/jantimon/html-webpack-plugin#user-content-options
* 删除 html 配置，并入 pageEntries 中

### 2018-05-17 v0.8.37

* 解决Thread-loader创建的子进程中无法加载 tua 中已安装的npm包的问题

### 2018-05-14 v0.8.36
* 增加在 `pageEntries` 方法中，支持 css 和 js 的内嵌配置 `inlineSource`
* 修复若干 bug

### 2018-04-30 v0.8.31
* 修正服务端HMR后内容不更新的问题

### 2018-04-27 v0.8.29
* 支持服务端多入口配置

注意：serverEntry 值类型改为Object

### 2018-03-27 v0.8.26
* 支持异步加载块 import()

### 2018-03-26 v0.8.25
* uglify 压缩打包默认输出 sourcemap

### 2018-03-15 v0.8.23
* 增加测试阶段服务端（node）sourcemap 支持
* 增加服务端线上环境 sourcemap 支持

### 2017-11-20 v0.8.19
* 开发模式兼容 windows
* loader配置路径兼容 windows /转为\

### 2017-11-16 v0.8.18
* 解决使用 server.mfs 方法时，因 webpack 未打包好html文件造成的时序问题
* 更新 webpack-dev-server

### 2017-11-15 v0.8.17
* 解决 pageEntrys 中 htmlsrc 使用同样的模板，导致 server.mfs 无法通过源路径找到生成的html的问题

### 2017-11-8 v0.8.15
* 解决 .cache-loader 找不到的时序问题

### 2017-11-2 v0.8.14
* node端代码打包也支持profile查看打包后的模块了
* 解决服务端代码external外部模块找不到模块的问题

### 2017-11-1 v0.8.13
* 修复了路由挂载post请求无效的问题。
serve-index 会过滤掉所有的非 `GET` 和 `HEAD` 请求，需要在此之前处理 koa-router 的挂载

### 2017-10-30 v0.8.12
* 调整了koa router中间件的挂载位置，使不影响koa其他中间件的挂载（setup和before等）
* 更换了koa中的 connect-history-api-fallback

### 2017-10-30 v0.8.10
* 优化了对模板html的读取，现抽象出 server.mfs 方法用于读取html文件

### 2017-10-24 v0.8.7
* dll 文件自动插入html，无需再手动引用

### 2017-10-19 v0.8.4
* serverEntry 模块支持 es6 的 export default 形式

### 2017-10-19 v0.8.1
* webpack-dev-server 增加配置，支持在使用webpack--dev-middleware 之前和之后配置中间件

### 2017-10-18 v0.8.0
* 支持 SSR， 服务端 js 支持热更新
* webpack-dev-sever 扩展支持 Koa2

### 2017-08-09 v0.7.3
* 更新依赖库版本
* 更新webpack-dev-server到2.8.0

### 2017-08-09 v0.7.0
* 修复windows下项目配置文件tua.js在命令执行时会被系统默认打开的问题，改为更加合理的 .tuarc，tua命令在windows下会优先打开同名文件
**注意: 旧项目中的 tua.js 会被自动重新命名为 .tuarc，请注意提交 .tuarc 到代码仓库。**

### 2017-08-03 v0.6.5
* 增强 cssEnhance 配置的能力，支持本地css loader，支持自定义postcss配置

### 2017-08-02 v0.6.4
* 修复 postcss 配置文件在 windows 中的生成的路径问题

### 2017-07-31 v0.6.3
* 去掉 webpack-chunk-hash 插件，此插件会导致内容不同的 manifest 文件名重名问题

### 2017-07-26 v0.6.1
* webpack 版本升级到 v3.4.1
* uglify 版本升级到 v3.0.6
* extract-text-webpack-plugin 版本升级到 v3.0.0

### 2017-07-26 v0.5.29
紧急修复 chunk-manifest-webpack-plugin v1.1.1 版本带来的 bug，暂时固定版本到 1.1.0
error 如下：
```shell
ERROR in chunk manifest [entry]
scripts/[name]_[chunkhash]_aaa.js
Chunk.entry was removed. Use hasRuntime()
```
