You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
7.9 KiB
208 lines
7.9 KiB
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.createBabelLoaderFromEnvironment = void 0;
|
|
const core_1 = require("@babel/core");
|
|
const paths_1 = require("@expo/config/paths");
|
|
const chalk_1 = __importDefault(require("chalk"));
|
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
const getenv_1 = require("getenv");
|
|
const path_1 = __importDefault(require("path"));
|
|
const resolve_from_1 = __importDefault(require("resolve-from"));
|
|
const env_1 = require("../env");
|
|
// Source maps are resource heavy and can cause out of memory issue for large source files.
|
|
const shouldUseSourceMap = (0, getenv_1.boolish)('GENERATE_SOURCEMAP', true);
|
|
const getModule = (name) => path_1.default.join('node_modules', name);
|
|
// Only compile files from the react ecosystem.
|
|
const includeModulesThatContainPaths = [
|
|
getModule('react-native'),
|
|
getModule('react-navigation'),
|
|
getModule('expo'),
|
|
getModule('unimodules'),
|
|
getModule('@react'),
|
|
getModule('@expo'),
|
|
getModule('@use-expo'),
|
|
getModule('@unimodules'),
|
|
getModule('native-base'),
|
|
getModule('styled-components'),
|
|
];
|
|
const excludedRootPaths = [
|
|
'/node_modules',
|
|
'/bower_components',
|
|
'/.expo/',
|
|
// Prevent transpiling webpack generated files.
|
|
'(webpack)',
|
|
];
|
|
const parsedPackageNames = [];
|
|
// TODO: Bacon: Support internal packages. ex: react/fbjs
|
|
function packageNameFromPath(inputPath) {
|
|
const modules = inputPath.split('node_modules/');
|
|
const libAndFile = modules.pop();
|
|
if (!libAndFile)
|
|
return null;
|
|
if (libAndFile.charAt(0) === '@') {
|
|
const [org, lib] = libAndFile.split('/');
|
|
return org + '/' + lib;
|
|
}
|
|
else {
|
|
const components = libAndFile.split('/');
|
|
const first = components.shift();
|
|
return first || null;
|
|
}
|
|
}
|
|
function logPackage(packageName) {
|
|
if (!parsedPackageNames.includes(packageName)) {
|
|
parsedPackageNames.push(packageName);
|
|
console.log(chalk_1.default.cyan('\nCompiling module: ' + chalk_1.default.bold(packageName)));
|
|
}
|
|
}
|
|
function ensureRoot(possibleProjectRoot) {
|
|
if (typeof possibleProjectRoot === 'string') {
|
|
return path_1.default.resolve(possibleProjectRoot);
|
|
}
|
|
return (0, paths_1.getPossibleProjectRoot)();
|
|
}
|
|
function generateCacheIdentifier(projectRoot, version = '1') {
|
|
const filename = path_1.default.join(projectRoot, 'foobar.js');
|
|
const cacheKey = `babel-cache-${version}-`;
|
|
const partial = (0, core_1.loadPartialConfig)({
|
|
filename,
|
|
cwd: projectRoot,
|
|
sourceFileName: filename,
|
|
});
|
|
return `${cacheKey}${JSON.stringify(partial.options)}`;
|
|
}
|
|
/**
|
|
* Creates a Rule for loading Application code and packages from the Expo ecosystem.
|
|
* This method attempts to recreate how Metro loads ES modules in the `node_modules` folder.
|
|
*
|
|
* @param env
|
|
* @internal
|
|
*/
|
|
function createBabelLoaderFromEnvironment(env) {
|
|
var _a;
|
|
const mode = (0, env_1.getMode)(env);
|
|
const locations = env.locations || (0, env_1.getPaths)(env.projectRoot, env);
|
|
const appConfig = env.config || (0, env_1.getConfig)(env);
|
|
const { build = {} } = appConfig.web;
|
|
const { babel = {} } = build;
|
|
return createBabelLoader({
|
|
projectRoot: locations.root,
|
|
mode,
|
|
platform: env.platform,
|
|
babelProjectRoot: babel.root || locations.root,
|
|
verbose: babel.verbose,
|
|
include: [...(babel.include || []), ...(((_a = env.babel) === null || _a === void 0 ? void 0 : _a.dangerouslyAddModulePathsToTranspile) || [])],
|
|
use: babel.use,
|
|
});
|
|
}
|
|
exports.createBabelLoaderFromEnvironment = createBabelLoaderFromEnvironment;
|
|
/**
|
|
* A complex babel loader which uses the project's `babel.config.js`
|
|
* to resolve all of the Unimodules which are shipped as ES modules (early 2019).
|
|
* @category loaders
|
|
*/
|
|
function createBabelLoader({
|
|
/**
|
|
* The webpack mode: `"production" | "development"`
|
|
*/
|
|
mode, projectRoot: inputProjectRoot, babelProjectRoot, include = [], verbose, platform = 'web', useCustom, ...options } = {}) {
|
|
const ensuredProjectRoot = ensureRoot(babelProjectRoot);
|
|
const modules = [...includeModulesThatContainPaths, ...include];
|
|
const customUse = options.use || {};
|
|
const customUseOptions = customUse.options || {};
|
|
const isProduction = mode === 'production';
|
|
const projectRoot = inputProjectRoot || (0, paths_1.getPossibleProjectRoot)();
|
|
let presetOptions = {
|
|
// Explicitly use babel.config.js instead of .babelrc
|
|
babelrc: false,
|
|
// Attempt to use local babel.config.js file for compiling project.
|
|
configFile: true,
|
|
};
|
|
if (!fs_extra_1.default.existsSync(path_1.default.join(projectRoot, 'babel.config.js')) &&
|
|
!fs_extra_1.default.existsSync(path_1.default.join(projectRoot, '.babelrc'))) {
|
|
// If no babel config exists then fallback on the default `babel-preset-expo`
|
|
// which is installed with `expo`.
|
|
const modulePath = resolve_from_1.default.silent(projectRoot, 'babel-preset-expo');
|
|
if (modulePath) {
|
|
presetOptions = {
|
|
babelrc: false,
|
|
configFile: false,
|
|
presets: [modulePath],
|
|
};
|
|
}
|
|
else {
|
|
console.log(chalk_1.default.yellow('\u203A Webpack failed to locate a valid Babel config'));
|
|
}
|
|
}
|
|
presetOptions = {
|
|
...presetOptions,
|
|
...(customUseOptions || {}),
|
|
sourceType: 'unambiguous',
|
|
root: ensuredProjectRoot,
|
|
compact: isProduction,
|
|
// Babel sourcemaps are needed for debugging into node_modules
|
|
// code. Without the options below, debuggers like VSCode
|
|
// show incorrect code and set breakpoints on the wrong lines.
|
|
sourceMaps: shouldUseSourceMap,
|
|
inputSourceMap: shouldUseSourceMap,
|
|
};
|
|
let cacheIdentifier = customUseOptions.cacheIdentifier;
|
|
if (!cacheIdentifier) {
|
|
try {
|
|
cacheIdentifier = generateCacheIdentifier(ensuredProjectRoot);
|
|
}
|
|
catch (error) {
|
|
console.log(chalk_1.default.black.bgRed(`The project's Babel config is invalid: ${error.message}`));
|
|
throw error;
|
|
}
|
|
}
|
|
presetOptions.cacheIdentifier = cacheIdentifier;
|
|
presetOptions.cacheCompression = false;
|
|
presetOptions.cacheDirectory =
|
|
customUseOptions.cacheDirectory ||
|
|
path_1.default.join(ensuredProjectRoot, '.expo', platform, 'cache', mode || 'development', 'babel-loader');
|
|
presetOptions.caller = {
|
|
__dangerous_rule_id: 'expo-babel-loader',
|
|
bundler: 'webpack',
|
|
platform,
|
|
mode,
|
|
};
|
|
return {
|
|
test: /\.(mjs|[jt]sx?)$/,
|
|
// Can only clobber test
|
|
// Prevent clobbering the `include` and `use` values.
|
|
...options,
|
|
include(inputPath) {
|
|
for (const possibleModule of modules) {
|
|
if (inputPath.includes(path_1.default.normalize(possibleModule))) {
|
|
if (verbose) {
|
|
const packageName = packageNameFromPath(inputPath);
|
|
if (packageName)
|
|
logPackage(packageName);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
// Is inside the project and is not one of designated modules
|
|
if (inputPath.includes(ensuredProjectRoot)) {
|
|
for (const excluded of excludedRootPaths) {
|
|
if (inputPath.includes(path_1.default.normalize(excluded))) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
use: {
|
|
...customUse,
|
|
loader: require.resolve('babel-loader'),
|
|
options: presetOptions,
|
|
},
|
|
};
|
|
}
|
|
exports.default = createBabelLoader;
|
|
//# sourceMappingURL=createBabelLoader.js.map
|