varan
Version:
A webpack starter kit for offline-first bring-your-own-code apps with server side rendering
174 lines • 8.58 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = require("lodash");
const path_1 = __importDefault(require("path"));
const detect_port_alt_1 = __importDefault(require("detect-port-alt"));
const listr_1 = __importDefault(require("listr"));
const chalk_1 = __importDefault(require("chalk"));
const wait_on_1 = __importDefault(require("wait-on"));
const emojis_1 = __importDefault(require("./emojis"));
const getConfigs_1 = __importDefault(require("./getConfigs"));
const buildAndRunDevServer_1 = __importDefault(require("./buildAndRunDevServer"));
const buildServer_1 = __importDefault(require("./buildServer"));
const getCompilerStats_1 = __importDefault(require("./getCompilerStats"));
const runServer_1 = __importDefault(require("./runServer"));
const createServerConfig_1 = __importDefault(require("../webpack/createServerConfig"));
const createClientConfig_1 = __importDefault(require("../webpack/createClientConfig"));
// Init
const getOpts = (options) => lodash_1.defaults({}, options, {
verbose: false,
configs: [createServerConfig_1.default, createClientConfig_1.default],
devServerProtocol: 'http',
devServerHost: process.env.HOST || 'localhost',
devServerPort: process.env.DEV_PORT ? parseInt(process.env.DEV_PORT, 10) : 3000,
serverHost: process.env.HOST || 'localhost',
serverPort: process.env.PORT ? parseInt(process.env.PORT, 10) : undefined,
env: 'development',
appDir: process.cwd(),
args: process.argv.includes('--') ? process.argv.slice(process.argv.indexOf('--') + 1) : [],
openBrowser: false,
waitForServer: true,
});
// Exports
async function watch(options) {
const opts = getOpts(options);
// Load configs
if (opts.configs.length > 2) {
throw new Error('Too many config files provided. Maximum two config files are supported in `watch` mode.');
}
const configs = getConfigs_1.default(opts.configs, opts);
const clientConfig = configs.find((c) => !c.target || c.target === 'web');
const serverConfig = configs.find((c) => c.target === 'node');
// Check if config is valid
if (configs.length >= 2 && (!clientConfig || !serverConfig)) {
throw new Error('One or more invalid config files provided. Maximum of one config file per target is supported.');
}
const taskOptions = {
showSubtasks: true,
renderer: opts.verbose ? 'default' : 'silent',
nonTTYRenderer: opts.verbose ? 'verbose' : 'silent',
};
const tasks = new listr_1.default([
{
title: 'Prepare',
task: async () => {
// Prepare
opts.devServerPort = await detect_port_alt_1.default(opts.devServerPort, opts.devServerHost);
opts.serverPort = await detect_port_alt_1.default((opts.serverPort && opts.serverPort !== opts.devServerPort && opts.serverPort) || opts.devServerPort + 1, opts.serverHost);
process.env.HOST = opts.serverHost;
opts.serverHost = process.env.HOST;
opts.devServerWSPort = await detect_port_alt_1.default(opts.devServerPort + 10, opts.devServerHost);
process.env.PORT = opts.serverPort.toString();
process.env.BABEL_ENV = opts.env;
return `${chalk_1.default.green(emojis_1.default.success)} Preparations completed successfully`;
},
},
{
title: 'Build',
task: () => new listr_1.default([
{
title: 'Build and start client development server',
enabled: () => !!clientConfig,
task: async (ctx) => {
opts.devServerProxy = !!serverConfig;
const devServerOpts = Object.assign(Object.assign({}, opts), { waitForPromise: new Promise((resolve, reject) => {
if (opts.waitForServer && !!serverConfig) {
wait_on_1.default({
resources: [`tcp:${opts.serverHost}:${opts.serverPort}`],
}, (err) => {
if (err)
return reject(err);
return resolve();
});
}
else
resolve();
}) });
ctx.client = await buildAndRunDevServer_1.default(clientConfig, opts.devServerHost, opts.devServerPort, devServerOpts);
return `${chalk_1.default.green(emojis_1.default.success)} Development server built successfully!`;
},
},
{
title: 'Build server',
enabled: () => !!serverConfig,
task: async (ctx) => {
const serverOpts = Object.assign({}, opts);
ctx.server = await buildServer_1.default(serverConfig, serverOpts);
return `${chalk_1.default.green(emojis_1.default.success)} Server built successfully!`;
},
},
], {
showSubtasks: true,
concurrent: true,
renderer: opts.silent ? 'silent' : 'default',
}),
},
{
title: 'Calculate statistics',
task: (ctx) => {
ctx.totals = getCompilerStats_1.default([ctx.server && ctx.server.stats, ctx.client && ctx.client.stats].filter(Boolean));
return `${chalk_1.default.green(emojis_1.default.success)} Build statistics calculated successfully`;
},
},
{
title: 'Start server',
enabled: (ctx) => !!ctx.server,
task: async (ctx) => {
const rootPath = lodash_1.get(ctx, 'server.compiler.options.output.path', null);
const entryFile = lodash_1.get(ctx, 'server.compiler.options.output.filename', null);
if (rootPath && entryFile) {
const serverOpts = Object.assign(Object.assign({}, opts), { entry: path_1.default.resolve(rootPath, entryFile) });
const { server } = (await runServer_1.default(serverOpts));
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
ctx.server.runner = server;
}
return `${chalk_1.default.green(emojis_1.default.success)} Server started successfully`;
},
},
], taskOptions);
/**
* Watch project
*/
// Set up the task queue
const result = await tasks.run();
// Create watching helpers
const clientWatcher = result.client
? {
warnings: result.client.warnings,
compiler: result.client.compiler,
runner: result.client.runner,
async close() {
return Promise.all([
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
result.client && result.client.runner && new Promise((resolve) => result.client.runner.close(resolve)),
].filter(Boolean));
},
}
: null;
const serverWatcher = result.server
? {
warnings: result.server.warnings,
compiler: result.server.compiler,
runner: result.server.runner,
watcher: result.server.watcher,
async close() {
return Promise.all([
new Promise((resolve) => result.server && result.server.watcher.close(resolve)),
new Promise((resolve) => {
if (result.server) {
result.server.runner.once('close', resolve);
result.server.runner.kill();
}
}),
]);
},
}
: null;
const close = async () => Promise.all([serverWatcher && serverWatcher.close(), clientWatcher && clientWatcher.close()].filter(Boolean));
return { close, client: clientWatcher, server: serverWatcher, totals: result.totals, options: opts };
}
exports.default = watch;
//# sourceMappingURL=watch.js.map