# create-kwai-app

## 用法

### 安装要求

请确保您使用的`Node`版本`>=14`

### 安装

```bash

npm install create-kwai-app -g

#or

yarn global add create-kwai-app

```


### 初始化 kwai 应用

使用我们内置的模板为你在本地创建一个应用。你可以使用 `cka init -h` 查看更多选项。

```bash
cka init [name]
```




### 开发 kwai 应用

借助 `webpack-dev-server` 启动开发服务器，它采用 `bundle` 方式进行本地预览，同时借助于热更新插件实时编译修改的文件。需要注意的是，cka pre 与 cka build 在构建产物方面使用一致的配置信息， 这有助于在本地验证构建产物的一致性。

```bash

npm run start

#or

cka pre

```

### 构建 kwai 应用

将项目构建到一个静态的 dist/ 目录中，你可以在任何地方部署该目录。你可以通过配置自定义你的构建。

```bash

npm run build

#or

cka build -m=production

```


### 查看所有命令/参数

通过 --help 标记将输出有帮助的信息。

```bash
cka --help
```

## 配置

### 零配置

Kwai 是一个真正实现零配置的构建工具。`零配置`，顾名思义，并不是指不需要配置，而是指在大多数情况下，配置信息对用户不可见。Kwai 内置了所有依赖方的默认配置，
并且收敛了其配置项的读取方式，提供了唯一的配置文件入口，这仅在你需要定制开发的情况下才用得到。对于绝大多数用户来说，你可以在完全无配置的情况下，将系统正常运行起来。

Kwai 配置项的读取，遵循一个由外向内的优先级，即 命令行参数`cli option` 高于 用户配置文件`config/default.js` 高于 Kwai `内置option`，对于每一级来说，你都不需要提供全量配置，通常是定制某项就提供某项，
而未提供的选项，会默认读取后一级。这样的设置剔除了干扰项，保证每一项配置都反映用户的真实意图。

![零配置优先级](https://s2-10684.ssrcdn.com/kos/nlav10684/jia-test/zero-config-priority.png)


### 配置文件

如果你在 项目根目录 下提供 `config/default.js` 文件路径，那么 Kwai 将会自动解析它。

`config/`是约定的所有配置文件的固定目录，除 `default.js` 和 `.env.*` 以外，用户自行扩展的插件配置文件也建议放于此目录下。

一个最基础的配置文件是这样的：

```javascript
// default.js
module.exports = {
  // 配置选项
}
```

配置选项分为共享配置、开发服务器配置、预览服务器配置、打包配置以及lint配置等几类，且所有配置项都不是必须的，以实现零配置的最高目标。

### 环境变量

为了你的安全，Kwai 只支持以 `Kwai_*` 开头的环境变量。我们这样做是因为Web应用中的所有内容都会被发送到浏览器上，我们不希望你不小心将敏感的密钥/环境变量分享给公共Web应用程序。
用 `Kwai_` 作为你的前端Web环境变量的前缀有很好的语义，它们也便于更好的分享。

### 设置环境变量

为了避免`default.js`中出现较多的环境判断逻辑，我们使用了 [dotenv-flow](https://github.com/kerimdzhanov/dotenv-flow) 来设置环境变量，
同时支持根据不同的业务环境设置如下多文件的形式进行设置。

```md
.
├─ config
│  ├─ .env
│  ├─ .env.staging
│  ├─ .env.prt
│  └─ .env.online
└─ package.json
```

比如当env值为staging时, 则会依次读取`.env`, `.env.staging`文件，并取它们所有变量的合集，同时`.env.staging`文件会覆盖掉`.env`文件中相同key的变量。

### 读取环境变量

你可以通过 `import.meta.env` 或 `process.env` 直接在web应用中读取环境变量。如果你曾经在 Create React App 或任何Webpack应用程序中使用过 `process.env`，其行为是完全一样的。

#### MODE + WEB_ENV

需要特别注意的是，Kwai 将代码的运行模式与业务环境区分开来，比如 `MODE` 代表的是 `development|production|test` 的运行模式,
而 `WEB_ENV` 代表的是 `staging|prt|online` 的业务环境。

设置 `process.env. NODE_ENV` 值，可以直接修改 `MODE` 值，根据开发和构建来改变应用行为。在 `Kwai dev` 期间，MODE 值被设置为 `development`，而在 `Kwai build` 期间被设置为 `production`。
在你的应用中使用 MODE 而不是 `process.env. NODE_ENV`。

```typescript
export const getMode: () => string | undefined = () => import.meta.env.MODE;
export const getWebEnv: () => string | undefined = () => import.meta.env.WEB_ENV;

export const isStagingMode: boolean = import.meta.env.WEB_ENV === 'staging';
export const isPrtMode: boolean = import.meta.env.WEB_ENV === 'prt';
export const isOnlineMode: boolean = import.meta.env.WEB_ENV === 'online';

export const isTestEnv: boolean = import.meta.env.MODE === 'test';
export const isDevelopmentEnv: boolean = import.meta.env.MODE === 'development';
export const isProductionEnv: boolean = import.meta.env.MODE === 'production';
```

你也可以在HTML文件中使用环境变量。所有出现的 `%Kwai_*%` 将在构建时被替换。 这些环境变量是在构建时静态地注入到你的应用中的，而不是在运行时。

### 共享配置

#### type

- **类型：** `string`
- **默认：** `web`

  项目应用的类型，值为 `web` 或 `lib`，分别指web工程或库工程，主要用在打包时声明使用不同的构建引擎。也可以通过命令行 `--type` 选项来重写。

#### env

- **类型：** `string`
- **默认：** `staging`，`prt`，`online`

  在配置中指明代码运行的业务环境。也可以通过命令行 `--env` 选项来重写，在代码中可通过 `import.meta.env.WEB_ENV` 读取。

#### mode

- **类型：** `string`
- **默认：** `test`，`development`，`production`

  在配置中指明代码运行的环境模式。也可以通过命令行 `--mode` 选项来重写，在代码中可通过 `import.meta.env.MODE` 读取。

#### logLevel

- **类型：** `string`
- **默认：** `info`

  系统日志级别。合法的值包括以下几种：`debug` | `info` | `warn` | `error` | `silent`。也可以通过命令行 `--logLevel` 选项来重写。

##### browserslist

- **类型：** `string[]`

- **默认：**

```javascript
// config/default.js
module.exports = {
  browserslist :   [
    "> 0.2% in CN",
    "last 2 versions",
    "Firefox ESR",
    "Android >= 5",
    "iOS >= 10",
    "not dead",
    "not ie < 11",
    "not op_mini all"
  ]
}
```

[Browserslist](https://aaronflower.github.io/essay/Browserslist.html) 是一个前端项目配置工具，功能是在前端工具之间共享目标环境的浏览器信息。
上述配置是我们团队规范约定的浏览器兼容目标，一般情况下你不需要修改。在打包时，browserslist 的配置会被 webpack 默认读取。

#### mount

- **类型：** `Record<string, string | Partial<MountEntry>>`
- **默认：**

```javascript
// config/default.js
module.exports = {
  mount : {
    "src": { "url": "/dist" },
    "public": { "url": "/", "static": true }
  }
}
```

将本地目录映射到构建的项目中的自定义 URL。

- `mount.url`|`string`|`required`: 要挂载到的 URL。
- `mount.static`|`boolean`|`optional`| 默认值：`false`: 如果为 true，则不在此目录中构建文件。直接从磁盘复制并提供给浏览器。
- `mount.resolve`|`boolean`|`optional`| 默认值：`true`：如果是 false，就不会在 JS、CSS 和 HTML 文件中解析 JS 和 CSS 引入，而将代码中的 import 操作直接传给浏览器。
- `mount.dot`|`boolean`|`optional`| 默认值:`false`：如果为 true，在最终构建时包含其它类型文件（例如：.htaccess）。

#### alias

- **类型：** `Record<string, string>`
- **默认：**

```javascript
// config/default.js
module.exports = {
  alias : {
    "@/": "./src/"
  }
}
```

配置目录和包的 import 别名。


#### externals

- **类型：** `Record<string, string>`
- **默认：**

```javascript
// config/default.js
module.exports = {
  externals : {
    react: {
      root: 'React',
      commonjs2: 'react',
      commonjs: 'react',
      amd: 'react',
    },
    'react-dom': {
      root: 'ReactDOM',
      commonjs2: 'react-dom',
      commonjs: 'react-dom',
      amd: 'react-dom',
    }
  }
}
```
配置不需要被 webpack 处理的目录或包名。

##### plugins

- **类型：** `包含 pluginName 的对象数组或对象数组[pluginName, pluginOptions]`
- **默认：**

```javascript
// config/default.js
var DashboardPlugin = require('webpack-dashboard/plugin');

module.exports = {
  plugins: {
    webpack: [ new DashboardPlugin({'plugin-option': false}) ],
    babel: [["./self_babel_plugin.js",{'plugin-option': false}]]
  }
}
```

plugins 包括了 `babel`、`webpack` 插件。

#### loaders

- **类型：** `object`
- **默认：**

```javascript
// config/default.js

const theme = require("./theme");

module.exports = {
  loaders:{
    less:{
      lessOptions:{
        modifyVars: theme,
        javascriptEnabled: true,
      }
    }
  }
}
```

loaders 为 webpack 专有的对象，主要用来处理各种格式的文件转换。其内置属性有 `less`、`sass`、`css`、`style`、`postcss` 以及 `url`，分别对应着各自的loader插件，用法如上例所示。



### 开发预览服务器配置

#### previewOptions.port

- **类型：** `number`
- **默认：** `9527`

预览服务器的运行端口。

#### previewOptions.secure

- **类型：** `boolean`
- **默认：**  `true`

预览服务器启用https服务。

#### previewOptions.hostname

- **类型：** `string`
- **默认：** `localhost`

预览服务器的运行主机名。

#### previewOptions.open

- **类型：** `boolean`
- **默认：** `true`

默认自动打开浏览器。

#### previewOptions.hot

- **类型：** `boolean`
- **默认：** `true`

默认开启热更新服务。

#### previewOptions.allowedHosts

- **类型：** `string | string[]`
- **默认：** `all`

默认允许所有域名访问。同 webpack 的 allowedHosts 配置，可选值为 'auto' | 'all' | [string]。

#### previewOptions.headers

- **类型：** `object`
- **默认：** ``

配置headers参数，同 webpack 的 `devServer` 中 headers。配置举例：

```javascript
// config/default.js
module.exports = {
  previewOptions: {
    headers: {'Access-Control-Allow-Origin': '*'}
  }
}
```

#### previewOptions.proxy

- **类型：** `object`
- **默认：** ``

配置代理服务器，同 webpack 的 `devServer` 中 proxy。配置举例：

```javascript
// config/default.js
module.exports = {
  previewOptions:{
    proxy: {
      "/api":"https://s.staging.kuaishou.com/rest/"
    }
  }
}
```

### 构建配置

#### buildOptions. name

- **类型：** `string`
- **默认：**  `index`
- **适用范围：** `lib`

构建产物的文件名。

#### buildOptions.input

- **类型：** `string[]`
- **默认：** `[src/index.ts]`
- **适用范围：** `lib`

构建时的入口文件。

#### buildOptions.output

- **类型：** `string|function`
- **默认：** `build`
- **适用范围：** `web|lib`

构建产物的相关配置，等同于 webpack 的 output 配置。

常见的配置如下：

```javascript
// config/default.js
module.exports = {
  buildOptions:{
    output: {
      "path": path.join("...","dist"),
      "publicPath": "/",
      "filename": "[name].[contenthash].js"
    }
  }
}
```

buildOptions 的配置会同时影响到 preview模式，因为他们共同一套相同的 webpack构建参数。

如果某些配置在 development 与 production 模式下不一致，可以将 output 做为一个函数进行配置，如：

```javascript
// config/default.js
module.exports = {
  buildOptions:{
    output:(mode)=>({
        publicPath : mode==='production' ? `https://ali2.a.kwimgs.com/udata/pkg/eshop/${pkg.name}` : `https://flash.corp.kuaishou.com/static/${pkg.name}`
    })
  }
}
```

#### buildOptions.format

- **类型：** `string`
- **默认：** `cjs,esm,umd`
- **适用范围：** `lib`

构建的产物格式。

#### buildOptions.extractCss

- **类型：** `boolean`
- **默认：** `false`
- **适用范围：** `lib`

抽离出css成单独文件。


#### buildOptions.minify

- **类型：** `boolean`
- **默认：** `true`
- **适用范围：** `web|lib`

压缩构建的产物。

#### buildOptions.sourcemap

- **类型：** `boolean`
- **默认：** `true`
- **适用范围：** `web|lib`

生成 sourcemap。

#### buildOptions.extensions

- **类型：** `string[]`
- **默认：** `['.tsx', '.ts', '.js', '.jsx']`
- **适用范围：** `web|lib`

等同于 webpack 的 resolve 参数的 extensions。

#### buildOptions.extraHtmlFilename

- **类型：** `string`
- **默认：**
- **适用范围：** `web`

默认情况下 htmlWebpackPlugin 会根据模板生成一个 `index.html` 目标文件。有时候情况下，你还可以通过此参数，额外添加另一个目标文件，比如 `index.txt`。

## 版本

### 0.1.0

- init version
