# apack

服务于蚂蚁的静态构建打包工具, 和 webpack 类似, 但区别在于:

* apack 采用微内核设计, 由外部 loader 直接告知模块依赖关系.
* apack 采用多线程和磁盘缓存, 加速构建.
* 平均构建速度基本都在毫秒级, 在禁用磁盘缓存情况下, 构建速度也远快于 webpack.

## 快速上手

* 首先, `package.json` 里面添加配置:

````json
"entry": {
  "index": "./src/entry/index.jsx" // 如果你的入口不是这个, 或者有多个 entry, 请修改此处
},
"devDependencies": {
  "@alipay/milk": "*",
  "@alipay/milk-apack": "*"
},
"scripts": {
  "milk": "milk"
}
````

如果你的项目使用了通过 `<script>` 标签引入的外部库, 比如 `jQuery`, 那么还需要在 `package.json` 里面配置:

````json
"externals": {
  "jquery": "jQuery" // 如果有还有其它库, 也一并在此添加
}
````


执行 `tnpm install`.

* 然后, 在项目根目录添加 `milk.js` 文件:

````js
var apack = require('@alipay/milk-apack');
exports.middlewares = [
apack({
  publicPath: '.'
})
];
````

* 最后, 执行 `tnpm run milk`, 然后浏览器访问 `http://127.0.0.1:8000/`.

注意, 该快速上手假设你使用了 `antd` 的标准脚手架, 即: 项目根目录有 `index.html` 文件, 该文件引用的静态资源都位于根目录下, 即 `<script src='./index.js'></script>`, `<link href='./index.css'/>`

如果你的项目不满足上面的约束, 请参考[自定义配置文件]()一节.

### 参数配置

以下参数都为可选参数. 

````js
var apack = require('@alipay/milk-apack');
exports.middlewares = [
apack({
  publicPath: '.', // 静态 html 文件路径
  outputPath: '.', // 构建产生的文件所在路径
  disableCache: false, // 是否禁用缓存, 不推荐开启
  babelExclude: ['node_modules'], // babel 处理的文件需要不满足哪些匹配, 默认排除 node_modules 目录. 如果为 null 代表不忽略文件.
  babelInclude: null, // babel 处理的文件需要满足的匹配, null 代表包含所有文件.
  customConfig: function(originConfig) { // 对默认的配置进行订制
    // 该示例展示了对于多 entry 的项目, 在开发阶段通过配置环境变量, 优化为只构建其中当前关心的 entry
    var oneEntry = process.env.ENTRY; 
    if (oneEntry) {
      var newEntry = {};
      newEntry[oneEntry] = originConfig.entry[oneEntry];
      originConfig.entry = newEntry;
    }
    
    return originConfig;
  }
})
];
````

默认情况下, `babel` 会处理 `node_modules` 目录之外的文件. 如果 `node_modules` 目录里面某个组件是 jsx 源码版本需要处理, 
可以用如下方式配置:

````js
var apack = require('@alipay/milk-apack');
var path = require('path');
function resolve(dir) {
  return path.resolve(process.cwd(), dir);
}
exports.middlewares = [
apack({
  babelExclude: null, // 不忽略任何文件
  babelInclude: [resolve('./src'), resolve('./node_modules/@alipay/opbase-biz-components/src')] // 必须匹配这两个目录
})
];
````

通过以上方式, 已经可以满足大部分中台项目的构建. 如果还想加入自定义的文件处理器(loader)等高级配置,
请使用以下方式使用 apack.

## 自定义配置文件

* 首先, 在 `package.json` 中添加配置:

````json
"scripts": {
  "apack-build": "apack -o ./dist"
},
"devDependencies": {
  "@alipay/apack": "^0.0.1",
  "@alipay/apack-babel-loader": "^0.0.1",
  "@alipay/apack-css-handler": "^0.0.1",
  "@alipay/apack-css-loader": "^0.0.1",
  "@alipay/apack-js-handler": "^0.0.1",
  "@alipay/apack-js-loader": "^0.0.1",
  "@alipay/apack-less-loader": "^0.0.1"
}
````

* 然后, 执行 `tnpm install`. 完成后, 在项目根目录新建 `apack.config.js` 文件:

````js
'use strict';

const jsLoader = require('@alipay/apack-js-loader');
const cssLoader = require('@alipay/apack-css-loader');
const lessLoader = require('@alipay/apack-less-loader');
const jsxLoader = require('@alipay/apack-babel-loader');
const scriptHandler = require('@alipay/apack-js-handler');
const styleHandler = require('@alipay/apack-css-handler');

const path = require('path');

module.exports = {
  disableWatch: false, // 是否禁用监控. 默认为 false. 和 webpack 不一样的是, apack 默认开启监控. 当 process.env.NODE_ENV === 'production' 时强制为 true
  disableCache: false, // 是否禁用缓存，默认为 false。当 process.env.NODE_ENV === 'production' 时强制为 true
  compress: true, // 是否压缩代码，默认为 false，当 process.env.NODE_ENV === 'production' 时默认为 true
  outputPath: '.',  // 打包代码的存放目录，默认为当前项目根目录（即.）。 命令行里可以用 -o, --output-path 指定从而增盖该参数
  resolve: {
    extensions: ['.js', '.jsx', '.less', '.css']
  },
  entry: {
    index: './src/entry/index.jsx'
  },
  loader: [
    jsxLoader({
      include: [path.join(__dirname, 'src')],
    }),
    jsLoader(),
    cssLoader(),
    lessLoader()
  ],
  handler: [
    scriptHandler({
      filename: '[name].js'
    }),
    styleHandler({
      filename: '[name].css'
    })
  ]
}
````

注意, 请将该文件里的 `entry` 项改成你的项目的入口.

* 最后, 执行:
````bash
$ tnpm run apack-build
````

然后就可以在 `./dist` 目录里面找到构建好的文件.

## Dev-Server

如果想能够像 `webpack-dev-server` 一样的开发, 可以使用 `@alipay/milk`. 

Milk 是一个极轻量的 koa 中间件容器封装, 本身不做太多事. `apack` 提供了一个 koa 标准中间件, 可以让 Milk 加载.

* 首先, 在 `package.json` 中添加:

````json
"scripts": {
  "milk": "milk"
}
"devDependencies": {
  "koa-static": "^2.0.0",
  "@alipay/milk": "^0.3.1"
}
````

* 然后, 执行 `tnpm install`. 完成后, 在项目根目录添加 `milk.js` 文件:

````js
var staticServe = require('koa-static');
var apack = require('@alipay/apack');
var serve = require('koa-static');

exports.middlewares = [

staticServe('.'),

apack.middleware()

]
````

* 最后, 执行:

````bash
$ tnpm run milk
````

## External

如果你在开发时启用 mock 功能, 或联调阶段代理数据, 可以在 milk 中配置使用更多的 koa 中间件. 详情请参考: [Milk 快速指南](http://gitlab.alipay.net/alipay-cd/milk/blob/master/Milk%20%E5%BF%AB%E9%80%9F%E6%8C%87%E5%8D%97.md)
