@tarojs/webpack-runner
Version:
webpack runner for taro
265 lines • 11.1 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.customizeChain = void 0;
const helper_1 = require("@tarojs/helper");
const detectPort = require("detect-port");
const path = require("path");
const url_1 = require("url");
const webpack = require("webpack");
const WebpackDevServer = require("webpack-dev-server");
const build_conf_1 = require("./config/build.conf");
const dev_conf_1 = require("./config/dev.conf");
const devServer_conf_1 = require("./config/devServer.conf");
const prod_conf_1 = require("./config/prod.conf");
const utils_1 = require("./utils");
const chain_1 = require("./utils/chain");
const logHelper_1 = require("./utils/logHelper");
const customizeChain = (chain, modifyWebpackChainFunc, customizeFunc) => __awaiter(void 0, void 0, void 0, function* () {
if (modifyWebpackChainFunc instanceof Function) {
yield modifyWebpackChainFunc(chain, webpack);
}
if (customizeFunc instanceof Function) {
customizeFunc(chain, webpack);
}
});
exports.customizeChain = customizeChain;
const buildProd = (appPath, config, appHelper) => __awaiter(void 0, void 0, void 0, function* () {
const webpackChain = (0, prod_conf_1.default)(appPath, config, appHelper);
yield (0, exports.customizeChain)(webpackChain, config.modifyWebpackChain, config.webpackChain);
if (typeof config.onWebpackChainReady === 'function') {
config.onWebpackChainReady(webpackChain);
}
const webpackConfig = webpackChain.toConfig();
const compiler = webpack(webpackConfig);
const onBuildFinish = config.onBuildFinish;
compiler.hooks.emit.tapAsync('taroBuildDone', (compilation, callback) => __awaiter(void 0, void 0, void 0, function* () {
if (typeof config.modifyBuildAssets === 'function') {
yield config.modifyBuildAssets(compilation.assets);
}
callback();
}));
return new Promise((resolve, reject) => {
(0, logHelper_1.bindProdLogger)(compiler);
compiler.run((err, stats) => {
if (err) {
(0, logHelper_1.printBuildError)(err);
if (typeof onBuildFinish === 'function') {
onBuildFinish({
error: err,
stats: null,
isWatch: false
});
}
return reject(err);
}
if (typeof onBuildFinish === 'function') {
onBuildFinish({
error: err,
stats,
isWatch: false
});
}
resolve();
});
});
});
const buildDev = (appPath, config, appHelper) => __awaiter(void 0, void 0, void 0, function* () {
var _a;
const conf = (0, build_conf_1.default)(config);
const routerConfig = config.router || {};
const routerMode = routerConfig.mode || 'hash';
const routerBasename = routerConfig.basename || '/';
const publicPath = (0, utils_1.parsePublicPath)(conf.publicPath);
const outputPath = path.join(appPath, conf.outputRoot);
const _b = config.devServer || {}, { proxy: customProxy = [] } = _b, customDevServerOption = __rest(_b, ["proxy"]);
const webpackChain = (0, dev_conf_1.default)(appPath, config, appHelper);
const onBuildFinish = config.onBuildFinish;
yield (0, exports.customizeChain)(webpackChain, config.modifyWebpackChain, config.webpackChain);
const isMultiRouterMode = routerMode === 'multi';
const proxy = [];
if (isMultiRouterMode) {
const customRoutes = (routerConfig === null || routerConfig === void 0 ? void 0 : routerConfig.customRoutes) || {};
const routerBasename = routerConfig.basename || '/';
const getEntriesRoutes = (customRoutes = {}) => {
const conf = [];
for (let key in customRoutes) {
const path = customRoutes[key];
key = (0, utils_1.addLeadingSlash)(key);
if (typeof path === 'string') {
conf.push([key, (0, utils_1.addLeadingSlash)(path)]);
}
else if ((path === null || path === void 0 ? void 0 : path.length) > 0) {
conf.push(...path.map(p => [key, (0, utils_1.addLeadingSlash)(p)]));
}
}
return conf;
};
const bypass = req => {
var _a, _b, _c, _d;
if (((_a = req.headers.accept) === null || _a === void 0 ? void 0 : _a.indexOf('html')) !== -1) {
const pagePath = (0, utils_1.stripTrailingSlash)((0, utils_1.stripBasename)(req.path, routerBasename));
if (pagePath === '') {
return (0, utils_1.addHtmlSuffix)(appHelper.appConfig.entryPagePath || ((_b = appHelper.appConfig.pages) === null || _b === void 0 ? void 0 : _b[0]));
}
const pageIdx = ((_c = appHelper.appConfig.pages) !== null && _c !== void 0 ? _c : []).findIndex(e => (0, utils_1.addLeadingSlash)(e) === pagePath);
if (pageIdx > -1) {
return (0, utils_1.addHtmlSuffix)((_d = appHelper.appConfig.pages) === null || _d === void 0 ? void 0 : _d[pageIdx]);
}
const customRoutesConf = getEntriesRoutes(customRoutes);
const idx = getEntriesRoutes(customRoutes).findIndex(list => list[1] === pagePath);
if (idx > -1) {
// NOTE: 自定义路由
return (0, utils_1.addHtmlSuffix)(customRoutesConf[idx][0]);
}
}
};
proxy.push({
context: [routerBasename],
bypass
});
}
if (!(customProxy instanceof Array)) {
proxy.push(...Object.entries(customProxy).map(([url, options = {}]) => {
const item = {
context: [url]
};
if (typeof options === 'string') {
item.target = options;
}
else {
Object.assign(item, options);
}
return item;
}));
}
if (typeof config.onWebpackChainReady === 'function') {
config.onWebpackChainReady(webpackChain);
}
const devServerOptions = config.isBuildNativeComp
? { writeToDisk: true }
: (0, helper_1.recursiveMerge)({
publicPath,
contentBase: outputPath,
historyApiFallback: {
rewrites: [{
from: /./,
to: publicPath
}]
},
proxy,
}, devServer_conf_1.default, customDevServerOption);
if (((_a = devServerOptions.proxy) === null || _a === void 0 ? void 0 : _a.length) < 1) {
// Note: proxy 不可以为空数组
delete devServerOptions.proxy;
}
if (devServerOptions.host === 'localhost') {
devServerOptions.useLocalIp = false;
}
const originalPort = Number(devServerOptions.port);
const availablePort = yield detectPort(originalPort);
if (availablePort !== originalPort) {
console.log();
console.log(`预览端口 ${originalPort} 被占用, 自动切换到空闲端口 ${availablePort}`);
devServerOptions.port = availablePort;
}
let pathname;
if (routerMode === 'multi') {
pathname = '/';
}
else if (routerMode === 'browser') {
pathname = routerBasename;
}
else {
pathname = '/';
}
const devUrl = (0, url_1.format)({
protocol: devServerOptions.https ? 'https' : 'http',
hostname: (0, utils_1.formatOpenHost)(devServerOptions.host),
port: devServerOptions.port,
pathname
});
const webpackConfig = webpackChain.toConfig();
WebpackDevServer.addDevServerEntrypoints(webpackConfig, devServerOptions);
const compiler = webpack(webpackConfig);
(0, logHelper_1.bindDevLogger)(compiler, devUrl);
const server = new WebpackDevServer(compiler, devServerOptions);
compiler.hooks.emit.tapAsync('taroBuildDone', (compilation, callback) => __awaiter(void 0, void 0, void 0, function* () {
if (typeof config.modifyBuildAssets === 'function') {
yield config.modifyBuildAssets(compilation.assets);
}
callback();
}));
compiler.hooks.done.tap('taroBuildDone', stats => {
if (typeof onBuildFinish === 'function') {
onBuildFinish({
error: null,
stats,
isWatch: true
});
}
});
compiler.hooks.failed.tap('taroBuildDone', error => {
if (typeof onBuildFinish === 'function') {
onBuildFinish({
error,
stats: null,
isWatch: true
});
}
});
return new Promise((resolve, reject) => {
server.listen(devServerOptions.port, devServerOptions.host, err => {
if (err) {
reject(err);
return console.log(err);
}
resolve();
});
});
});
exports.default = (appPath, config) => __awaiter(void 0, void 0, void 0, function* () {
const newConfig = yield (0, chain_1.makeConfig)(config);
const app = new utils_1.AppHelper(newConfig.entry, {
sourceDir: path.join(appPath, config.sourceRoot || helper_1.SOURCE_DIR),
frameworkExts: newConfig.frameworkExts,
entryFileName: newConfig.entryFileName
});
if (newConfig.isWatch) {
try {
yield buildDev(appPath, newConfig, app);
}
catch (e) {
console.error(e);
}
}
else {
try {
yield buildProd(appPath, newConfig, app);
}
catch (e) {
console.error(e);
process.exit(1);
}
}
});
//# sourceMappingURL=index.js.map