okam-build
Version:
The build tool for Okam develop framework
248 lines (224 loc) • 7.25 kB
JavaScript
/**
* @file Babel processor option initialize
* @author sparklewhy@gmail.com
*/
;
/* eslint-disable fecs-min-vars-per-destructure */
const {resolve: resolveDep} = require('./npm');
const programPlugins = require('../js/plugins/babel-program-plugins');
const polyfillPlugin = require('../js/plugins/babel-polyfill-plugins');
const {normalPageConfig, normalizeComponentConfig} = require('./config');
const DEP_PLUGIN_NAME = 'dep';
/**
* The builtin babel plugins
*
* @const
* @type {Object}
*/
const BUILTIN_PLUGINS = {
[DEP_PLUGIN_NAME]: function (file, buildManager) {
return [
programPlugins.resolveDep,
{
resolveDepRequireId: resolveDep.bind(null, buildManager, file)
}
];
}
};
/**
* Initialize the mixin(Behavior) file
*
* @inner
* @param {Array.<string>} mixins the mixin file paths
* @param {Object} buildManager the build manager
* @param {Object} file the file that refers the mixin files
*/
function initMixinFile(mixins, buildManager, file) {
mixins && mixins.forEach(modulePath => {
let {resolvedModIds: cacheResolveModIds} = file;
let cacheInfo = cacheResolveModIds[modulePath];
let mixinFile = cacheInfo && cacheInfo.file;
if (mixinFile && !mixinFile.isBehavior) {
mixinFile.isBehavior = true;
}
});
}
/**
* Initialize filter config
*
* @param {Object} filters filter info
* @param {Object} buildManager the build manager
* @param {Object} file the file that owns the filter
*/
function initFilterConfig(filters, buildManager, file) {
if (!filters) {
return;
}
file.filters = filters;
}
/**
* Initialize the app/component/page config information.
* e.g., the `mixins` info defined in the component, the `config` defined in
* app entry script that will be extracted to `app.json`
*
* @inner
* @param {BuildManager} buildManager the build manager
* @param {string} key the cache key that the `config` info cached to the file
* @param {Object} file the file contains the config info
* @param {Object} info the extract config info
*/
function initConfigInfo(buildManager, key, file, info) {
buildManager.logger.trace('extract file config', file.path, info);
let {components, config = {}} = info;
if (file.isPageScript) {
initMixinFile(info.mixins, buildManager, file);
initFilterConfig(info.filters, buildManager, file);
config = normalPageConfig(config, components, file, buildManager);
}
else if (file.isComponentScript) {
initMixinFile(info.mixins, buildManager, file);
initFilterConfig(info.filters, buildManager, file);
config = normalizeComponentConfig(config, components, file, buildManager);
config.component = true;
}
else {
initMixinFile(info.mixins, buildManager, file);
}
file[key] = config;
}
/**
* Initialize the local polyfill plugins
*
* @inner
* @param {Array.<Object>} polyfills the polyfill list
* @param {Array} plugins the existed plugin list
*/
function initLocalPolyfillPlugins(polyfills, plugins) {
polyfills.forEach(item => {
let pluginItem = polyfillPlugin[item.type];
plugins.push([
pluginItem, {polyfill: item}
]);
});
}
/**
* Check whether has babel dep resolve plugin in the given plugin list
*
* @inner
* @param {Array} plugins the plugin list
* @return {boolean}
*/
function hasBabelDepPlugin(plugins) {
return plugins.some(item => {
let pluginItem = item;
if (Array.isArray(item)) {
pluginItem = item[0];
}
if (typeof pluginItem === 'string') {
return pluginItem === DEP_PLUGIN_NAME;
}
return pluginItem === programPlugins.resolveDep;
});
}
/**
* Normalize babel plugins
*
* @inner
* @param {Array} plugins the plugins to normalize
* @param {Object} file the file to process
* @param {BuildManager} buildManager the build manager
* @return {Array}
*/
function normalizeBabelPlugins(plugins, file, buildManager) {
if (typeof plugins === 'function') {
plugins = plugins(file);
}
plugins = plugins ? [].concat(plugins) : [];
if (!hasBabelDepPlugin(plugins)) {
// add npm resolve plugin
plugins.push(DEP_PLUGIN_NAME);
}
return (plugins || []).map(item => {
if (typeof item === 'string') {
let result = BUILTIN_PLUGINS[item];
if (typeof result === 'function') {
return result(file, buildManager);
}
}
return item;
});
}
/**
* Initialize babel processor options
*
* @param {Object} file the file to process
* @param {Object} processorOpts the processor options
* @param {BuildManager} buildManager the build manager
* @return {Object}
*/
function initBabelProcessorOptions(file, processorOpts, buildManager) {
processorOpts = Object.assign(
{}, buildManager.babelConfig, processorOpts
);
// init plugins
let plugins = normalizeBabelPlugins(processorOpts.plugins, file, buildManager);
// init app/page/component transform plugin
let configInitHandler = initConfigInfo.bind(
null, buildManager, 'config', file
);
let appBaseClass = buildManager.getOutputAppBaseClass();
let pluginOpts = {
appType: buildManager.appType,
config: configInitHandler
};
let filterOptions = buildManager.getFilterTransformOptions();
let enableMixinSupport = buildManager.isEnableMixinSupport();
let {api, framework, localPolyfill, polyfill} = buildManager.buildConf;
let getInitOptions = buildManager.getAppBaseClassInitOptions.bind(
buildManager, file
);
if (file.isEntryScript) {
Object.assign(pluginOpts, {
framework,
registerApi: api,
baseClass: appBaseClass && appBaseClass.app
});
// polyfill using local variable is prior to global polyfill
localPolyfill || (pluginOpts.polyfill = polyfill);
pluginOpts.getInitOptions = getInitOptions;
plugins.push([
programPlugins.app,
pluginOpts
]);
}
else if (file.isPageScript) {
Object.assign(pluginOpts, {
enableMixinSupport,
filterOptions,
tplRefs: file.tplRefs,
baseClass: appBaseClass && appBaseClass.page,
getInitOptions
});
plugins.push([programPlugins.page, pluginOpts]);
}
else if (file.isComponentScript) {
Object.assign(pluginOpts, {
enableMixinSupport,
filterOptions,
tplRefs: file.tplRefs,
baseClass: appBaseClass && appBaseClass.component,
getInitOptions
});
plugins.push([programPlugins.component, pluginOpts]);
}
else if (file.isBehavior) {
plugins.push([programPlugins.behavior, pluginOpts]);
}
// init local polyfill plugins
if (localPolyfill && !file.compiled) {
initLocalPolyfillPlugins(localPolyfill, plugins);
}
processorOpts.plugins = plugins;
return processorOpts;
}
module.exports = exports = initBabelProcessorOptions;