UNPKG

4.14 kBJavaScriptView Raw
1#!/usr/bin/env node
2
3/*
4 Copyright © 2018 Andrew Powell
5
6 This Source Code Form is subject to the terms of the Mozilla Public
7 License, v. 2.0. If a copy of the MPL was not distributed with this
8 file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10 The above copyright notice and this permission notice shall be
11 included in all copies or substantial portions of this Source Code Form.
12*/
13const path = require('path');
14
15const chalk = require('chalk');
16const importLocal = require('import-local');
17const parse = require('yargs-parser');
18const webpack = require('webpack');
19
20const pkg = require('../package.json');
21
22const { error: stderr } = console;
23const end = () => process.exit(0);
24const configTypes = {
25 function: (c, argv) => Promise.resolve(c(argv.env || {}, argv)),
26 object: (c) => Promise.resolve(c)
27};
28
29const help = chalk`
30 ${pkg.description}
31
32 {underline Usage}
33 $ wp [...options]
34
35 {underline Options}
36 --config A path to a webpack config file
37 --config.\{name\} A path to a webpack config file, and the config name to run
38 --help Displays this message
39 --silent Instruct the CLI to produce no console output
40 --version Displays webpack-nano and webpack versions
41
42 {underline Examples}
43 $ wp
44 $ wp --help
45 $ wp --config webpack.config.js
46 $ wp --config.serve webpack.config.js
47`;
48
49const doeet = async () => {
50 process.on('SIGINT', end);
51 process.on('SIGTERM', end);
52
53 const argv = parse(process.argv.slice(2));
54 const logPrefix = { ok: chalk.blue('⬡ webpack:'), whoops: chalk.red('⬢ webpack:') };
55 const log = {
56 error: (...args) => {
57 if (argv.silent) return;
58 args.unshift(logPrefix.whoops);
59 stderr(...args);
60 },
61 info: (...args) => {
62 if (argv.silent) return;
63 args.unshift(logPrefix.ok);
64 stderr(...args);
65 }
66 };
67
68 if (argv.help) {
69 stderr(help);
70 return;
71 }
72
73 if (argv.version || argv.v) {
74 stderr(`
75webpack-nano v${pkg.version}
76webpack v${webpack.version}
77`);
78 return;
79 }
80
81 let config = {};
82 let watchConfig;
83
84 // let's not process any config if the user hasn't specified any
85 if (argv.config) {
86 const configName = typeof argv.config !== 'string' ? Object.keys(argv.config)[0] : null;
87 // e.g. --config.batman webpack.config.js
88 const configPath = argv.config[configName] || argv.config;
89 let configExport = require(path.resolve(configPath)); // eslint-disable-line global-require, import/no-dynamic-require
90 const configType = typeof configExport;
91
92 if (configName) {
93 if (!Array.isArray(configExport)) {
94 throw new TypeError(
95 `A config with name was specified, but the config ${configPath} does not export an Array.`
96 );
97 }
98
99 configExport = configExport.find((c) => c.name === configName);
100
101 if (!configExport) {
102 throw new RangeError(`A config with name '${configName}' was not found in ${configPath}`);
103 }
104 }
105
106 config = await configTypes[configType](configExport, argv);
107 watchConfig = [].concat(config).find((c) => !!c.watch);
108 }
109
110 const compiler = webpack(config);
111 const done = (fatal, stats) => {
112 const hasErrors = stats && stats.hasErrors();
113
114 process.exitCode = Number(!!fatal || (hasErrors && !watchConfig));
115
116 if (fatal) {
117 log.error(fatal);
118 return;
119 }
120
121 const defaultStatsOptions = { colors: chalk.supportsColor, exclude: ['node_modules'] };
122 const { options = {} } =
123 []
124 .concat(compiler.compilers || compiler)
125 .reduce((a, c) => c.options.stats && c.options.stats) || {};
126
127 const result = stats.toString(options.stats == null ? defaultStatsOptions : options.stats);
128
129 log.info(result);
130 };
131
132 if (watchConfig) {
133 log.info('Watching Files');
134 compiler.watch(watchConfig.watchOptions || {}, done);
135 } else {
136 compiler.hooks.done.tap('webpack-nano', () => log.info('Build Finished'));
137 compiler.run(done);
138 }
139};
140
141process.on('unhandledRejection', (err) => {
142 stderr(err.stack);
143 process.exitCode = 1;
144});
145
146// eslint-disable-next-line no-unused-expressions
147importLocal(__filename) || doeet();
148
\No newline at end of file