inject-template.js 3.0 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
import {SNOWPACK_PUBLIC_BASE_URI, SNOWPACK_PUBLIC_PATH} from './env.js';
P
Peter Pan 已提交
18

19 20 21 22 23
import Logger from './log.js';
import {fileURLToPath} from 'url';
import fs from 'fs/promises';
import {minify} from 'html-minifier';
import path from 'path';
P
Peter Pan 已提交
24

25 26 27 28 29
const logger = new Logger('Inject template');

const cwd = path.dirname(fileURLToPath(import.meta.url));

const dist = path.resolve(cwd, '../dist');
P
Peter Pan 已提交
30 31 32 33 34 35
const input = path.join(dist, 'index.html');
const output = path.join(dist, 'index.tpl.html');

function envProviderTemplate(baseUri) {
    return `
        <script type="module">
36
            import * as env from '${baseUri}/__snowpack__/env.local.js'; window.__snowpack_env__ = env;
P
Peter Pan 已提交
37 38 39 40
        </script>
    `;
}

41
const ENV_PROVIDER = envProviderTemplate(SNOWPACK_PUBLIC_BASE_URI);
P
Peter Pan 已提交
42 43 44 45 46 47 48 49 50
const ENV_TEMPLATE_PROVIDER = envProviderTemplate('%BASE_URI%');

function injectProvider(content, provider) {
    const scriptPos = content.indexOf('<script ');
    return content.slice(0, scriptPos) + provider + content.slice(scriptPos);
}

function prependPublicPath(content, publicPath) {
    return content.replace(/\b(src|href)=(['"]?)([^'"\s>]*)/gi, (_matched, attr, quote, url) => {
51
        if (/^\/(_dist_|__snowpack__|web_modules|favicon.ico|imported-styles.css)\b/.test(url)) {
P
Peter Pan 已提交
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
            url = publicPath + url;
        }
        return attr + '=' + quote + url;
    });
}

async function writeMinified(file, content) {
    await fs.writeFile(
        file,
        minify(content, {
            collapseWhitespace: true,
            removeAttributeQuotes: true,
            removeComments: true,
            sortAttributes: true,
            sortClassName: true
        }),
        'utf-8'
    );
}

72 73 74
export default async () => {
    logger.start();
    logger.process('injecting env to index.html...');
P
Peter Pan 已提交
75
    const index = await fs.readFile(input, 'utf-8');
76
    const indexWithPublicPath = prependPublicPath(index, SNOWPACK_PUBLIC_PATH);
P
Peter Pan 已提交
77
    const injected = injectProvider(indexWithPublicPath, ENV_PROVIDER);
78
    logger.process('minifying index.html...');
P
Peter Pan 已提交
79
    await writeMinified(input, injected);
80
    logger.process('injecting env to index.tpl.html...');
P
Peter Pan 已提交
81 82
    const template = prependPublicPath(index, '%PUBLIC_URL%');
    const injectedTemplate = injectProvider(template, ENV_TEMPLATE_PROVIDER);
83
    logger.process('minifying index.tpl.html...');
P
Peter Pan 已提交
84
    await writeMinified(output, injectedTemplate);
85
    logger.end('Template injected.');
P
Peter Pan 已提交
86
};