Gulp 设置部署环境

总访客数量

概述

某些项目使用 jenkins 做自动构建,一份代码可能会部署到多个环境,如:正式环境、预发布环境、测试环境、本地开发环境。运维不可能每次都去手动改变我们的代码,所以,就需要前端可以针对不同的部署环境进行构建配置。对于多人维护的项目应该有一个可以统一的本地开发环境,不需要每个人再去配置。

依赖支持

本方案使用的是 gulp-preprocess 插件,该插件可以构建一个可配置的上下文供我们在构建时使用。

同时使用 gulp-connect 支持本地开发的服务。

代码讲解

这一部分按照一个完整的简单项目进行分解。

  1. 公共部分。一次性将需要用到的变量引入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    const { series, parallel, src, dest, watch } = require('gulp')
    const preprocess = require('gulp-preprocess')
    const connect = require('gulp-connect')
    const deleteFiles = require('delete')

    const DELETE_PATH = 'output/**'
    const OUTPUT_PATH = 'output/backend/'
    const COPY_PATH = [
    '**',
    '!node_modules/**',
    '!output/**',
    '!.gitignore',
    '!gulpfile.js',
    '!package-lock.json',
    '!package.json',
    '!src/interface.js', // 此文件为需要根据不同环境配置不同环境变量
    ]
  2. 清除文件。清除旧文件

    1
    2
    3
    function clean() {
    return deleteFiles.promise([DELETE_PATH])
    }
  3. 复制文件。该项目只需要复制特定文件到指定位置即可

    1
    2
    3
    4
    function copy() {
    return src(COPY_PATH)
    .pipe(dest(OUTPUT_PATH))
    }
  4. 处理特定文件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function buildInterface(){
    return src(INTERFACE_PATH)
    .pipe(preprocess({
    context: {
    // 此处可接受来自调用命令的 NODE_ENV 参数,默认为 online 线上环境
    NODE_ENV: process.env.NODE_ENV || 'online',
    },
    }))
    .pipe(dest(OUTPUT_PATH + 'src'))
    }
  5. 执行。

    1
    2
    3
    4
    5
    6
    7
    const build = series(
    clean,
    copy,
    buildInterface,
    )

    exports.build = build
  6. 本地开发服务器。

    1
    2
    3
    4
    5
    6
    7
    8
    function connectDist() {
    return connect.server({
    name: 'Dist App',
    root: 'output',
    port: 8052,
    livereload: true
    });
    }
  7. 本地开发服务器热更新。

    1
    2
    3
    4
    function connectReload(){
    return src(COPY_PATH)
    .pipe(connect.reload())
    }
  8. 本地开发文件变化监听。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    const buildReload = series(
    build,
    connectReload,
    )


    function watchFile(){
    return watch(COPY_PATH, buildReload)
    }

    exports.local = series(
    build,
    parallel(
    connectDist,
    watchFile,
    ),
    )

变量应用

in

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var interface = (function(){
return {
// @if NODE_ENV = 'local'
key: 'local',
loginPage: 'http://localhost:8052/backend/login.html',
backendapi: 'http://backendapi.qa.xxxx.me',
// @endif
// @if NODE_ENV = 'qa'
key: 'qa',
loginPage: 'http://backend.qa.xxxx.me/login.html',
backendapi: 'http://backendapi.qa.xxxx.me',
// @endif
// @if NODE_ENV = 'preview'
key: 'preview',
loginPage: 'http://backend.preview.xxxx.me/login.html',
backendapi: 'http://backendapi.preview.xxxx.me',
// @endif
// @if NODE_ENV = 'online'
key: 'online',
loginPage: 'http://backend.xxxx.me/login.html',
backendapi: 'http://backendapi.xxxx.me',
// @endif
}

})()

out local

1
2
3
4
5
6
7
8
var interface = (function(){
return {
key: 'local',
loginPage: 'http://localhost:8052/backend/login.html',
backendapi: 'http://backendapi.qa.xxxx.me',
}

})()

out online

1
2
3
4
5
6
7
8
var interface = (function(){
return {
key: 'online',
loginPage: 'http://backend.xxxx.me/login.html',
backendapi: 'http://backendapi.xxxx.me',
}

})()

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

const { series, parallel, src, dest, watch } = require('gulp')
const preprocess = require('gulp-preprocess')
const connect = require('gulp-connect')
const deleteFiles = require('delete')

const DELETE_PATH = 'output/**'
const OUTPUT_PATH = 'output/backend/'
const COPY_PATH = [
'**',
'!node_modules/**',
'!output/**',
'!.gitignore',
'!gulpfile.js',
'!package-lock.json',
'!package.json',
'!src/interface.js',
]
const INTERFACE_PATH = 'src/interface.js'

function clean() {
return deleteFiles.promise([DELETE_PATH])
}

function copy() {
return src(COPY_PATH)
.pipe(dest(OUTPUT_PATH))
}

function buildInterface(){
return src(INTERFACE_PATH)
.pipe(preprocess({
context: {
// 此处可接受来自调用命令的 NODE_ENV 参数,默认为 online 线上环境
NODE_ENV: process.env.NODE_ENV || 'online',
},
}))
.pipe(dest(OUTPUT_PATH + 'src'))
}

function connectDist() {
return connect.server({
name: 'Dist App',
root: 'output',
port: 8052,
livereload: true
});
}

function connectReload(){
return src(COPY_PATH)
.pipe(connect.reload())
}

const build = series(
clean,
copy,
buildInterface,
)

const buildReload = series(
build,
connectReload,
)


function watchFile(){
return watch(COPY_PATH, buildReload)
}


exports.build = build

exports.local = series(
build,
parallel(
connectDist,
watchFile,
),
)

调用

package.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"scripts": {
"local": "set NODE_ENV=local&&gulp local",
"qa": "set NODE_ENV=qa&&gulp build",
"preview": "set NODE_ENV=preview&&gulp build",
"online": "set NODE_ENV=online&&gulp build"
},
"devDependencies": {
"delete": "^1.1.0",
"gulp": "^4.0.2",
"gulp-connect": "^5.7.0",
"gulp-preprocess": "^3.0.3"
}
}

本地开发:npm run local
测试环境部署:npm run qa
预发布环境部署:npm run preview
线上环境部署:npm run online

参考

https://www.jianshu.com/p/bd2f97e16d86
https://www.npmjs.com/package/gulp-preprocess
https://www.npmjs.com/package/gulp-connect