index.ts 4.3 KB
Newer Older
P
Peter Pan 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/**
 * Copyright 2020 Baidu Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

17 18
/* eslint-disable no-console */

19
import {config} from 'dotenv';
20
import express from 'express';
21
import {promises as fs} from 'fs';
22
import path from 'path';
23 24 25
import resolve from 'enhanced-resolve';

config();
26

27
const isDev = process.env.NODE_ENV === 'development';
P
Peter Pan 已提交
28
const isDemo = !!process.env.DEMO;
29

30
const host = process.env.HOST || 'localhost';
31
const port = Number.parseInt(process.env.PORT || '', 10) || 8999;
32
const backend = process.env.BACKEND;
33
const delay = Number.parseInt(process.env.DELAY || '', 10);
34
const pingUrl = process.env.PING_URL;
P
Peter Pan 已提交
35

36
const root = path.dirname(resolve.sync(__dirname, '@visualdl/core'));
37

38
const app = express();
39

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
async function parseTemplate() {
    const template = await fs.readFile(path.resolve(root, 'index.tpl.html'), {encoding: 'utf-8'});
    return template.replace(/%(.+?)%/g, (_matched, key) => process.env[key] ?? '');
}

async function extendEnv() {
    const content = await fs.readFile(path.resolve(root, '__snowpack__/env.local.js'), {encoding: 'utf-8'});
    const match = content.match(/export default\s*({.*})/);
    const env = JSON.parse(match[1]);
    return Object.keys(env).reduce((m, key) => {
        if (process.env[key] != null) {
            m[key] = process.env[key];
        }
        return m;
    }, env);
}

57
async function start() {
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
    require('@visualdl/core/builder/environment');

    // snowpack uses PUBLIC_URL & MODE in template
    // https://www.snowpack.dev/#environment-variables
    process.env.MODE = process.env.NODE_ENV;
    if (process.env.PUBLIC_PATH != null) {
        process.env.PUBLIC_URL = process.env.PUBLIC_PATH;
    }

    const baseUri = process.env.SNOWPACK_PUBLIC_BASE_URI;
    const apiUrl = process.env.SNOWPACK_PUBLIC_API_URL;

    const template = await parseTemplate();
    const env = await extendEnv();

73
    if (backend) {
P
Peter Pan 已提交
74
        const {createProxyMiddleware} = await import('http-proxy-middleware');
75 76
        app.use(
            apiUrl,
77 78 79 80 81
            createProxyMiddleware({
                target: backend,
                changeOrigin: true
            })
        );
P
Peter Pan 已提交
82
    } else if (isDemo) {
P
Peter Pan 已提交
83 84 85 86 87 88
        try {
            const {default: demo} = await import('@visualdl/demo');
            app.use(apiUrl, demo);
        } catch {
            console.warn('Demo is not installed. Please rebuild server.');
        }
P
Peter Pan 已提交
89
    } else if (isDev) {
90 91
        const {middleware: mock} = await import('@visualdl/mock');
        app.use(apiUrl, mock({delay: delay ? () => Math.random() * delay : 0}));
92 93
    } else {
        console.warn('Server is running in production mode but no backend address specified.');
94 95
    }

96
    if (baseUri !== '') {
97
        app.get('/', (_req, res) => {
98
            res.redirect(baseUri);
99 100 101
        });
    }

102
    if (pingUrl && pingUrl !== '/' && pingUrl !== baseUri && pingUrl.startsWith('/')) {
103
        app.get(pingUrl, (_req, res) => {
104
            res.type('text/plain').status(200).send('OK!');
P
Peter Pan 已提交
105 106 107
        });
    }

108 109 110 111 112 113 114
    app.get(`${baseUri}/__snowpack__/env.local.js`, (_req, res) => {
        res.type('.js')
            .status(200)
            .send(`export default ${JSON.stringify(env)};`);
    });

    app.use(baseUri || '/', express.static(root, {index: false}));
115

116
    app.get(/\.wasm/, (_req, res, next) => {
117 118 119 120
        res.type('application/wasm');
        next();
    });

121
    app.get('*', (_req, res) => {
122
        res.type('.html').status(200).send(template);
123
    });
124

125
    const server = app.listen(port, host, () => {
126 127 128
        process.send?.('ready');
        console.log(`> Ready on http://${host}:${port}`);
        process.on('SIGINT', () => {
129
            server.close(err => {
130 131 132 133 134 135 136
                if (err) {
                    throw err;
                }
                process.exit(0);
            });
        });
    });
137 138 139 140 141 142 143
}

if (require.main === module) {
    start();
}

export default start;
144

145
export {app};