Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

📦 san-cli-build 发包2.1.3 & 增减san deploy命令 #340

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions docs/deploy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# 生产打包

`san deploy`是远程部署命令,与 `san build --remote` 相比,支持更复杂的远程目标配置,可通过 `san-cli` 集成也可通过安装 `san-deploy-cli` 独立使用。

## 使用命令

```bash
san deploy [target]
```

- target:推送目标,具体传输路径由 `san.deploy.config.js` 指定。

### 配置相关

`san.deploy.config.js`的内容是一个 Node.js 的 CommandJS 格式,默认配置是:`

- `--config -c` 指定配置文件,默认读取项目根目录下的 san.deploy.config.js
- `--watch -w` 开启监听模式,默认不开启,仅推送一次

### 配置文件

以 `san deploy test` 命令为例,推送至 test指定的远程环境。san.deploy.config.js 文件内容如下:

```js
module.exports = {
test: {
root: 'output',
disableFsr: false,
ignore: [/(^|[\/\\])\../, '**/node_modules/**'],
host: 'http://machine.com:8999',
receiver: '',
rule: [
{
match: '**', // glob
to: '/path/to/dest',
},
{
match: ['output/**', 'template/**'],
to: '/path/to/dest'
}
],
replace: { // object or array
from: new RegExp('http://static.com', 'ig'), // string/reg
to: 'http://dev.com:8888/'
}
}
};
```

#### `root`
监听的根目录,可省略,默认 "."(当前目录)

#### `ignore`
忽略的文件,值为 `string` or `array`, 符合 [anymatch](https://www.npmjs.com/package/anymatch) 规范

#### `receiver`
远程服务的 receiver.php 地址,receiver.php 文件内容[参考](https://github.com/fex-team/fis3-deploy-http-push/blob/master/receiver.php)

#### `disableFsr`
是否禁用 fsr 安全部署服务,值为 true 或 false,默认是 false ,使用 fsr 安全部署服务。

若远端机器使用脚本等方式接收,须禁用 fsr ,将此项置为 true )

#### `host`
配置此项的前提是,disableFsr 为 false,启用了 fsr 安全部署服务,用于替换原来的 reciever 配置,拼接成该此项设置的域名。

#### `rule`
部署规则,值为 `object` or `array`, 其中每一项内,指定了文件匹配规则 match, 部署到远端的 路径 to。
match 值为 string or array,支持 glob匹配文件 规则。

#### `replace`
替换规则,值为 `object` or `array`, 通常用于将静态文件 cdn 替换为测试环境静态服务地址。其中每一项需指定:原字符(from,支持正则及 string),替换的目标字符(to)

### 执行部署

```bash
# 单次构建并远程部署
san deploy test
# 监听产出每次变动自动执行远程部署
san build test --watch
```

> 实现依赖 [deploy-files](https://github.com/wanwu/deploy-files) 的 upload.js文件
> 一些不适于安装 san cli 的工程可使用 [san-deploy-cli](https://www.npmjs.com/package/san-deploy-cli) 完成推送。
2 changes: 1 addition & 1 deletion packages/san-cli-build/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "san-cli-build",
"description": "San-CLI build command",
"version": "2.1.1",
"version": "2.1.3",
"main": "index.js",
"license": "MIT",
"engines": {
Expand Down
3 changes: 3 additions & 0 deletions packages/san-cli-deploy/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
__tests__
docs/**
node_modules/**
24 changes: 24 additions & 0 deletions packages/san-cli-deploy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# san-cli-deploy

san-cli-deploy 是 [San](https://github.com/baidu/san) CLI 工具中远程部署功能,与san build --remote
相比,支持更复杂的远程目标配置,可通过 `san-cli` 集成也可通过安装 `san-deploy-cli` 独立使用。
san deploy 命令的执行主体。

## 使用文档

请移步[San-CLI 文档](https://ecomfe.github.io/san-cli)

## 安装

```shell
$ npm install --save-dev san-cli-deploy
```

## 测试

执行命令

```bash
#执行__tests__下所有测试文件
yarn test
```
34 changes: 34 additions & 0 deletions packages/san-cli-deploy/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Copyright (c) Baidu Inc. All rights reserved.
*
* This source code is licensed under the MIT license.
* See LICENSE file in the project root for license information.
*
* @file deploy
*/

const {logger, chalk} = require('san-cli-utils/ttyLogger');

exports.command = 'deploy [target]';
exports.description = 'Send file to the remote target machine';
exports.builder = {
watch: {
alias: 'w',
type: 'boolean',
default: false,
describe: 'Watch mode'
},
config: {
alias: 'c',
type: 'string',
describe: 'Deploy config file'
}
};

exports.handler = argv => {
if (!argv.target) {
logger.error(chalk.red('Deploy target not found, please set [target]'));
return;
}
require('./run')(argv);
};
32 changes: 32 additions & 0 deletions packages/san-cli-deploy/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "san-cli-deploy",
"description": "San-CLI deploy command",
"version": "1.0.2",
"main": "index.js",
"license": "MIT",
"engines": {
"node": ">=12.13.0"
},
"author": "zttonly",
"repository": {
"type": "git",
"url": "git+https://github.com/ecomfe/san-cli.git",
"directory": "packages/san-cli-deploy"
},
"bugs": {
"url": "https://github.com/ecomfe/san-cli/issues"
},
"homepage": "https://ecomfe.github.io/san-cli",
"keywords": [
"san",
"deploy",
"san.js",
"san-cli"
],
"dependencies": {
"chokidar": "^3.5.3",
"deploy-files": "^0.2.6",
"graceful-fs": "^4.2.10",
"san-cli-utils": "^1.0.5"
}
}
104 changes: 104 additions & 0 deletions packages/san-cli-deploy/run.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* Copyright (c) Baidu Inc. All rights reserved.
*
* This source code is licensed under the MIT license.
* See LICENSE file in the project root for license information.
*
* @file deploy
* @author zttonly
*/

const {resolve, isAbsolute} = require('path');
const fs = require('graceful-fs');
const chokidar = require('chokidar');

const {logger} = require('san-cli-utils/ttyLogger');
const {textCommonColor} = require('san-cli-utils/color');
const {findExisting} = require('san-cli-utils/path');
const Upload = require('deploy-files/upload');

const loadConfig = (filepath, cwd) => {
// 读取远程目标配置
let configFile = filepath;
let config = null;
if (configFile && typeof configFile === 'string') {
configFile = isAbsolute(configFile) ? configFile : resolve(cwd, configFile);
if (!fs.existsSync(configFile)) {
configFile = false;
logger.warn(`Config file \`${filepath}\` is not exists!`);
}
}

if (!configFile) {
// 主动查找 cwd 目录的config
configFile = findExisting(['san.deploy.config.js', '.san.deploy.config.js'], cwd);
}

if (configFile) {
config = require(configFile);

if (typeof config !== 'object') {
logger.error(`${textCommonColor(configFile)}: Expected object type.`);
}
}
return config;
};

const arrify = (value = []) => (Array.isArray(value) ? value : [value]);

module.exports = function apply(argv) {
const cwd = process.cwd();
const config = loadConfig(argv.config, cwd);
if (!config) {
logger.error('Please set default deploy configuration!');
return;
}

if (!argv.target || !config[argv.target]) {
logger.error('Deploy target invalid!');
return;
}
const deployObj = config[argv.target];
const {
root = '.',
disableFsr = false,
ignore = [/(^|[\/\\])\../, '**/node_modules/**'],
host,
receiver,
watchOptions = {}
} = deployObj;

const up = new Upload({
disableFsr,
host,
receiver,
replace: arrify(deployObj.replace),
});
const rule = arrify(deployObj.rule);
rule.forEach(item => {
let timer = null;
const watcher = chokidar.watch(item.match, {
cwd: resolve(cwd, root),
ignored: ignore, // glob
persistent: argv.watch,
...watchOptions
});
const files = {};
watcher.on('all', (event, file) => {
const filePth = resolve(cwd, root, file);
if (event === 'add' || event === 'change') {
files[file] = fs.readFileSync(filePth);
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
up.upload({
to: item.to,
files
});
timer = null;
}, 500);
}
});
});
};
Loading