mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-14 18:12:09 +08:00
167 lines
3.3 KiB
TypeScript
167 lines
3.3 KiB
TypeScript
import { highlight } from 'cli-highlight';
|
|
import { merge } from 'webpack-merge';
|
|
import Config from 'webpack-chain';
|
|
import webpack from 'webpack';
|
|
|
|
import { applyExternalConfigs } from './helpers/externalConfigs';
|
|
import { determineProjectFlavor } from './helpers/flavor';
|
|
import { error, info } from './helpers/log';
|
|
import { configs } from './configuration';
|
|
import helpers from './helpers';
|
|
|
|
export type Platform = 'android' | 'ios' | string;
|
|
|
|
export interface IWebpackEnv {
|
|
[name: string]: any;
|
|
|
|
appPath?: string;
|
|
appResourcesPath?: string;
|
|
|
|
nativescriptLibPath?: string;
|
|
|
|
android?: boolean;
|
|
ios?: boolean;
|
|
|
|
production?: boolean;
|
|
report?: boolean;
|
|
hmr?: boolean;
|
|
|
|
// enable verbose output
|
|
verbose?: boolean;
|
|
// todo: add others
|
|
}
|
|
|
|
interface IChainEntry {
|
|
chainFn: any;
|
|
order?: number;
|
|
plugin?: string;
|
|
}
|
|
|
|
let webpackChains: IChainEntry[] = [];
|
|
let webpackMerges: any[] = [];
|
|
let explicitUseConfig = false;
|
|
let hasInitialized = false;
|
|
let currentPlugin: string | undefined;
|
|
/**
|
|
* @internal
|
|
*/
|
|
export let env: IWebpackEnv = {};
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
export function setCurrentPlugin(plugin: string) {
|
|
currentPlugin = plugin;
|
|
}
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
export function clearCurrentPlugin() {
|
|
currentPlugin = undefined;
|
|
}
|
|
|
|
////// PUBLIC API
|
|
export const defaultConfigs = configs;
|
|
export const Utils = helpers;
|
|
|
|
export function init(_env: IWebpackEnv) {
|
|
hasInitialized = true;
|
|
if (_env) {
|
|
env = _env;
|
|
}
|
|
}
|
|
|
|
export function useConfig(config: keyof typeof defaultConfigs | false) {
|
|
explicitUseConfig = true;
|
|
if (config) {
|
|
webpackChains.push({
|
|
order: -1,
|
|
chainFn: configs[config],
|
|
});
|
|
}
|
|
}
|
|
|
|
export function chainWebpack(
|
|
chainFn: (config: Config, env: IWebpackEnv) => any,
|
|
options?: { order?: number }
|
|
) {
|
|
webpackChains.push({
|
|
order: options?.order || 0,
|
|
chainFn,
|
|
plugin: currentPlugin,
|
|
});
|
|
}
|
|
|
|
export function mergeWebpack(
|
|
mergeFn: (
|
|
config: Partial<webpack.Configuration>,
|
|
env: IWebpackEnv
|
|
) => any | Partial<webpack.Configuration>
|
|
) {
|
|
webpackMerges.push(mergeFn);
|
|
}
|
|
|
|
export function resolveChainableConfig(): Config {
|
|
const config = new Config();
|
|
|
|
if (!explicitUseConfig) {
|
|
useConfig(determineProjectFlavor());
|
|
}
|
|
|
|
// apply configs from dependencies
|
|
// todo: allow opt-out
|
|
applyExternalConfigs();
|
|
|
|
webpackChains
|
|
.splice(0)
|
|
.sort((a, b) => {
|
|
return a.order - b.order;
|
|
})
|
|
.forEach(({ chainFn, plugin }) => {
|
|
try {
|
|
chainFn(config, env);
|
|
} catch (err) {
|
|
if (plugin) {
|
|
// print error with plugin name that causes it
|
|
error(`
|
|
Unable to apply chain function from: ${plugin}.
|
|
Error is: ${err}
|
|
`);
|
|
}
|
|
}
|
|
});
|
|
|
|
if (env.verbose) {
|
|
info('Resolved chainable config (before merges):');
|
|
info(highlight(config.toString(), { language: 'js' }));
|
|
}
|
|
|
|
return config;
|
|
}
|
|
|
|
export function resolveConfig(
|
|
chainableConfig = resolveChainableConfig()
|
|
): webpack.Configuration {
|
|
if (!hasInitialized) {
|
|
throw error('resolveConfig() must be called after init()');
|
|
}
|
|
|
|
let config = chainableConfig.toConfig();
|
|
|
|
// this applies webpack merges
|
|
webpackMerges.forEach((mergeFn) => {
|
|
if (typeof mergeFn === 'function') {
|
|
// mergeFn is a function with optional return value
|
|
const res = mergeFn(config, env);
|
|
if (res) config = merge(config, res);
|
|
} else if (mergeFn) {
|
|
// mergeFn is a literal value (object)
|
|
config = merge(config, mergeFn);
|
|
}
|
|
});
|
|
|
|
// return a config usable by webpack
|
|
return config;
|
|
}
|