@expo/webpack-config
Version:
A Webpack configuration used to bundle Expo websites with Expo CLI.
169 lines • 6.66 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getBabelLoaderRule = exports.styleLoaderRule = exports.fallbackLoaderRule = exports.imageLoaderRule = exports.avifImageLoaderRule = void 0;
const fs_1 = __importDefault(require("fs"));
const getenv_1 = require("getenv");
const mini_css_extract_plugin_1 = __importDefault(require("mini-css-extract-plugin"));
const createBabelLoader_1 = __importDefault(require("./createBabelLoader"));
const env_1 = require("../env");
const shouldUseSourceMap = (0, getenv_1.boolish)('GENERATE_SOURCEMAP', true);
// Inline resources as Base64 when there is less reason to parallelize their download. The
// heuristic we use is whether the resource would fit within a TCP/IP packet that we would
// send to request the resource.
//
// An Ethernet MTU is usually 1500. IP headers are 20 (v4) or 40 (v6) bytes and TCP
// headers are 40 bytes. HTTP response headers vary and are around 400 bytes. This leaves
// about 1000 bytes for content to fit in a packet.
const imageInlineSizeLimit = parseInt(process.env.IMAGE_INLINE_SIZE_LIMIT || '1000', 10);
// TODO: Merge this config once `image/avif` is in the mime-db
// https://github.com/jshttp/mime-db
exports.avifImageLoaderRule = {
test: [/\.avif$/],
type: 'asset',
mimetype: 'image/avif',
parser: {
dataUrlCondition: {
maxSize: imageInlineSizeLimit,
},
},
};
/**
* This is needed for webpack to import static images in JavaScript files.
* "url" loader works like "file" loader except that it embeds assets
* smaller than specified limit in bytes as data URLs to avoid requests.
* A missing `test` is equivalent to a match.
*
* @category loaders
*/
// TODO: Bacon: Move SVG
exports.imageLoaderRule = {
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/, /\.svg$/],
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: imageInlineSizeLimit,
},
},
};
/**
* "file" loader makes sure those assets get served by WebpackDevServer.
* When you `import` an asset, you get its (virtual) filename.
* In production, they would get copied to the `build` folder.
* This loader doesn't use a "test" so it will catch all modules
* that fall through the other loaders.
*
* @category loaders
*/
exports.fallbackLoaderRule = {
// Exclude `js` files to keep "css" loader working as it injects
// its runtime that would otherwise be processed through "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpacks internal loaders.
exclude: [/^$/, /\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
type: 'asset/resource',
};
/**
* Default CSS loader.
*
* @category loaders
*/
exports.styleLoaderRule = {
test: /\.(css)$/,
use: [require.resolve('style-loader'), require.resolve('css-loader')],
};
function getPossibleProjectRoot() {
return fs_1.default.realpathSync(process.cwd());
}
/**
* Create the fallback loader for parsing any unhandled file type.
*
* @param env
* @category loaders
*/
function createAllLoaders(env) {
env.projectRoot = env.projectRoot || getPossibleProjectRoot();
// @ts-ignore
env.config = env.config || (0, env_1.getConfig)(env);
// @ts-ignore
env.locations = env.locations || (0, env_1.getPaths)(env.projectRoot, env);
const isNative = ['ios', 'android'].includes(env.platform);
if (isNative) {
// TODO: Support fallback loader + assets
return [getBabelLoaderRule(env)];
}
const isEnvDevelopment = env.mode === 'development';
const isEnvProduction = env.mode === 'production';
const { publicPath: publicUrlOrPath } = (0, env_1.getPublicPaths)(env);
// common function to get style loaders
const getStyleLoaders = (cssOptions) => {
const loaders = [
isEnvDevelopment && require.resolve('style-loader'),
isEnvProduction && {
loader: mini_css_extract_plugin_1.default.loader,
// css is located in `static/css`, use '../../' to locate index.html folder
// in production `paths.publicUrlOrPath` can be a relative path
options: publicUrlOrPath.startsWith('.') ? { publicPath: '../../' } : {},
},
{
loader: require.resolve('css-loader'),
options: cssOptions,
},
].filter(Boolean);
return loaders;
};
return [
exports.avifImageLoaderRule,
exports.imageLoaderRule,
getBabelLoaderRule(env),
{
test: /\.(css)$/,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
modules: {
mode: 'icss',
},
}),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// This needs to be the last loader
exports.fallbackLoaderRule,
].filter(Boolean);
}
exports.default = createAllLoaders;
/**
* Creates a Rule for loading application code and packages that work with the Expo ecosystem.
* This method attempts to emulate how Metro loads ES modules in the `node_modules` folder.
*
* @param env partial Environment object.
* @category loaders
*/
function getBabelLoaderRule(env) {
var _a;
env.projectRoot = env.projectRoot || getPossibleProjectRoot();
// @ts-ignore
env.config = env.config || (0, env_1.getConfig)(env);
env.locations = env.locations || (0, env_1.getPaths)(env.projectRoot, env);
const { web: { build: { babel = {} } = {} } = {} } = env.config;
// TODO: deprecate app.json method in favor of env.babel
const { root, verbose, include = [], use } = babel;
const babelProjectRoot = root || env.projectRoot;
return (0, createBabelLoader_1.default)({
projectRoot: env.locations.root,
mode: env.mode,
platform: env.platform,
babelProjectRoot,
verbose,
include: [...include, ...(((_a = env.babel) === null || _a === void 0 ? void 0 : _a.dangerouslyAddModulePathsToTranspile) || [])],
use,
});
}
exports.getBabelLoaderRule = getBabelLoaderRule;
//# sourceMappingURL=createAllLoaders.js.map
;