|
|
"use strict";
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
|
value: true
|
|
|
});
|
|
|
exports.broadcastMessage = broadcastMessage;
|
|
|
exports.bundleAsync = bundleAsync;
|
|
|
exports.getUrlAsync = getUrlAsync;
|
|
|
exports.isTargetingNative = isTargetingNative;
|
|
|
exports.openAsync = openAsync;
|
|
|
exports.startAsync = startAsync;
|
|
|
exports.stopAsync = stopAsync;
|
|
|
function _devServer() {
|
|
|
const data = require("@expo/dev-server");
|
|
|
_devServer = function () {
|
|
|
return data;
|
|
|
};
|
|
|
return data;
|
|
|
}
|
|
|
function _symbolicateMiddleware() {
|
|
|
const data = require("@expo/dev-server/build/webpack/symbolicateMiddleware");
|
|
|
_symbolicateMiddleware = function () {
|
|
|
return data;
|
|
|
};
|
|
|
return data;
|
|
|
}
|
|
|
function devcert() {
|
|
|
const data = _interopRequireWildcard(require("@expo/devcert"));
|
|
|
devcert = function () {
|
|
|
return data;
|
|
|
};
|
|
|
return data;
|
|
|
}
|
|
|
function _betterOpn() {
|
|
|
const data = _interopRequireDefault(require("better-opn"));
|
|
|
_betterOpn = function () {
|
|
|
return data;
|
|
|
};
|
|
|
return data;
|
|
|
}
|
|
|
function _chalk() {
|
|
|
const data = _interopRequireDefault(require("chalk"));
|
|
|
_chalk = function () {
|
|
|
return data;
|
|
|
};
|
|
|
return data;
|
|
|
}
|
|
|
function _fsExtra() {
|
|
|
const data = _interopRequireDefault(require("fs-extra"));
|
|
|
_fsExtra = function () {
|
|
|
return data;
|
|
|
};
|
|
|
return data;
|
|
|
}
|
|
|
function _getenv() {
|
|
|
const data = _interopRequireDefault(require("getenv"));
|
|
|
_getenv = function () {
|
|
|
return data;
|
|
|
};
|
|
|
return data;
|
|
|
}
|
|
|
function path() {
|
|
|
const data = _interopRequireWildcard(require("path"));
|
|
|
path = function () {
|
|
|
return data;
|
|
|
};
|
|
|
return data;
|
|
|
}
|
|
|
function _formatWebpackMessages() {
|
|
|
const data = _interopRequireDefault(require("react-dev-utils/formatWebpackMessages"));
|
|
|
_formatWebpackMessages = function () {
|
|
|
return data;
|
|
|
};
|
|
|
return data;
|
|
|
}
|
|
|
function _webpack() {
|
|
|
const data = _interopRequireDefault(require("webpack"));
|
|
|
_webpack = function () {
|
|
|
return data;
|
|
|
};
|
|
|
return data;
|
|
|
}
|
|
|
function _webpackDevServer() {
|
|
|
const data = _interopRequireDefault(require("webpack-dev-server"));
|
|
|
_webpackDevServer = function () {
|
|
|
return data;
|
|
|
};
|
|
|
return data;
|
|
|
}
|
|
|
function _internal() {
|
|
|
const data = require("./internal");
|
|
|
_internal = function () {
|
|
|
return data;
|
|
|
};
|
|
|
return data;
|
|
|
}
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
|
const WEBPACK_LOG_TAG = 'expo';
|
|
|
let webpackDevServerInstance = null;
|
|
|
let webpackServerPort = null;
|
|
|
// A custom message websocket broadcaster used to send messages to a React Native runtime.
|
|
|
let customMessageSocketBroadcaster;
|
|
|
async function clearWebCacheAsync(projectRoot, mode) {
|
|
|
const cacheFolder = path().join(projectRoot, '.expo', 'web', 'cache', mode);
|
|
|
_internal().ProjectUtils.logInfo(projectRoot, WEBPACK_LOG_TAG, _chalk().default.dim(`Clearing ${mode} cache directory...`));
|
|
|
try {
|
|
|
await _fsExtra().default.remove(cacheFolder);
|
|
|
} catch {}
|
|
|
}
|
|
|
|
|
|
// Temporary hack while we implement multi-bundler dev server proxy.
|
|
|
const _isTargetingNative = ['ios', 'android'].includes(process.env.EXPO_WEBPACK_PLATFORM || '');
|
|
|
function isTargetingNative() {
|
|
|
return _isTargetingNative;
|
|
|
}
|
|
|
async function broadcastMessage(message, data) {
|
|
|
if (!webpackDevServerInstance || !(webpackDevServerInstance instanceof _webpackDevServer().default)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// Allow any message on native
|
|
|
if (customMessageSocketBroadcaster) {
|
|
|
customMessageSocketBroadcaster(message, data);
|
|
|
return;
|
|
|
}
|
|
|
if (message !== 'reload') {
|
|
|
// TODO:
|
|
|
// Webpack currently only supports reloading the client (browser),
|
|
|
// remove this when we have custom sockets, and native support.
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// TODO:
|
|
|
// Default webpack-dev-server sockets use "content-changed" instead of "reload" (what we use on native).
|
|
|
// For now, just manually convert the value so our CLI interface can be unified.
|
|
|
const hackyConvertedMessage = message === 'reload' ? 'content-changed' : message;
|
|
|
webpackDevServerInstance.sockWrite(webpackDevServerInstance.sockets, hackyConvertedMessage, data);
|
|
|
}
|
|
|
function createNativeDevServerMiddleware(projectRoot, {
|
|
|
port,
|
|
|
compiler,
|
|
|
forceManifestType
|
|
|
}) {
|
|
|
if (!isTargetingNative()) {
|
|
|
return null;
|
|
|
}
|
|
|
const nativeMiddleware = (0, _devServer().createDevServerMiddleware)(projectRoot, {
|
|
|
logger: _internal().ProjectUtils.getLogger(projectRoot),
|
|
|
port,
|
|
|
watchFolders: [projectRoot]
|
|
|
});
|
|
|
// Add manifest middleware to the other middleware.
|
|
|
// TODO: Move this in to expo/dev-server.
|
|
|
|
|
|
const useExpoUpdatesManifest = forceManifestType === 'expo-updates';
|
|
|
const middleware = useExpoUpdatesManifest ? _internal().ExpoUpdatesManifestHandler.getManifestHandler(projectRoot) : _internal().ManifestHandler.getManifestHandler(projectRoot);
|
|
|
nativeMiddleware.middleware.use(middleware).use('/symbolicate', (0, _symbolicateMiddleware().createSymbolicateMiddleware)({
|
|
|
projectRoot,
|
|
|
compiler,
|
|
|
logger: nativeMiddleware.logger
|
|
|
}));
|
|
|
return nativeMiddleware;
|
|
|
}
|
|
|
function attachNativeDevServerMiddlewareToDevServer(projectRoot, {
|
|
|
server,
|
|
|
middleware,
|
|
|
logger,
|
|
|
// Expo SDK 44 and lower
|
|
|
attachToServer,
|
|
|
// React Native +68 -- Expo SDK 45 and higher
|
|
|
messageSocketEndpoint,
|
|
|
eventsSocketEndpoint
|
|
|
}) {
|
|
|
if (attachToServer) {
|
|
|
// Hook up the React Native WebSockets to the Webpack dev server.
|
|
|
const {
|
|
|
messageSocket,
|
|
|
eventsSocket
|
|
|
} = attachToServer(server);
|
|
|
customMessageSocketBroadcaster = messageSocket.broadcast;
|
|
|
const logReporter = new (_devServer().LogReporter)(logger);
|
|
|
logReporter.reportEvent = eventsSocket.reportEvent;
|
|
|
(0, _devServer().attachInspectorProxy)(projectRoot, {
|
|
|
middleware,
|
|
|
server
|
|
|
});
|
|
|
} else {
|
|
|
// React Native +68
|
|
|
const logReporter = new (_devServer().LogReporter)(logger);
|
|
|
logReporter.reportEvent = eventsSocketEndpoint.reportEvent;
|
|
|
customMessageSocketBroadcaster = messageSocketEndpoint.broadcast;
|
|
|
(0, _devServer().attachInspectorProxy)(projectRoot, {
|
|
|
middleware,
|
|
|
server
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
async function startAsync(projectRoot, options = {}) {
|
|
|
var _config$devServer;
|
|
|
await stopAsync(projectRoot);
|
|
|
if (webpackDevServerInstance) {
|
|
|
_internal().ProjectUtils.logError(projectRoot, WEBPACK_LOG_TAG, _chalk().default.red(`Webpack is already running.`));
|
|
|
return null;
|
|
|
}
|
|
|
const fullOptions = transformCLIOptions(options);
|
|
|
const env = await getWebpackConfigEnvFromBundlingOptionsAsync(projectRoot, fullOptions);
|
|
|
if (fullOptions.clear) {
|
|
|
await clearWebCacheAsync(projectRoot, env.mode);
|
|
|
}
|
|
|
if (env.https) {
|
|
|
if (!process.env.SSL_CRT_FILE || !process.env.SSL_KEY_FILE) {
|
|
|
const ssl = await getSSLCertAsync({
|
|
|
name: 'localhost',
|
|
|
directory: projectRoot
|
|
|
});
|
|
|
if (ssl) {
|
|
|
process.env.SSL_CRT_FILE = ssl.certPath;
|
|
|
process.env.SSL_KEY_FILE = ssl.keyPath;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
const config = await loadConfigAsync(env);
|
|
|
const port = await getAvailablePortAsync({
|
|
|
projectRoot,
|
|
|
defaultPort: options.port
|
|
|
});
|
|
|
webpackServerPort = port;
|
|
|
_internal().ProjectUtils.logInfo(projectRoot, WEBPACK_LOG_TAG, `Starting Webpack on port ${webpackServerPort} in ${_chalk().default.underline(env.mode)} mode.`);
|
|
|
const protocol = env.https ? 'https' : 'http';
|
|
|
if (isTargetingNative()) {
|
|
|
await _internal().ProjectSettings.setPackagerInfoAsync(projectRoot, {
|
|
|
expoServerPort: webpackServerPort,
|
|
|
packagerPort: webpackServerPort
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// Create a webpack compiler that is configured with custom messages.
|
|
|
const compiler = (0, _webpack().default)(config);
|
|
|
|
|
|
// Create the middleware required for interacting with a native runtime (Expo Go, or a development build).
|
|
|
let nativeMiddleware = null;
|
|
|
if ((_config$devServer = config.devServer) !== null && _config$devServer !== void 0 && _config$devServer.before) {
|
|
|
nativeMiddleware = createNativeDevServerMiddleware(projectRoot, {
|
|
|
port,
|
|
|
compiler,
|
|
|
forceManifestType: options.forceManifestType
|
|
|
});
|
|
|
// Inject the native manifest middleware.
|
|
|
const originalBefore = config.devServer.before.bind(config.devServer.before);
|
|
|
config.devServer.before = (app, server, compiler) => {
|
|
|
var _nativeMiddleware;
|
|
|
originalBefore(app, server, compiler);
|
|
|
if ((_nativeMiddleware = nativeMiddleware) !== null && _nativeMiddleware !== void 0 && _nativeMiddleware.middleware) {
|
|
|
app.use(nativeMiddleware.middleware);
|
|
|
}
|
|
|
};
|
|
|
}
|
|
|
const server = new (_webpackDevServer().default)(compiler, config.devServer);
|
|
|
// Launch WebpackDevServer.
|
|
|
server.listen(port, _internal().WebpackEnvironment.HOST, function (error) {
|
|
|
if (nativeMiddleware) {
|
|
|
attachNativeDevServerMiddlewareToDevServer(projectRoot, {
|
|
|
server: this,
|
|
|
...nativeMiddleware
|
|
|
});
|
|
|
}
|
|
|
if (error) {
|
|
|
_internal().ProjectUtils.logError(projectRoot, WEBPACK_LOG_TAG, error.message);
|
|
|
}
|
|
|
if (typeof options.onWebpackFinished === 'function') {
|
|
|
options.onWebpackFinished(error);
|
|
|
}
|
|
|
});
|
|
|
webpackDevServerInstance = server;
|
|
|
await _internal().ProjectSettings.setPackagerInfoAsync(projectRoot, {
|
|
|
webpackServerPort
|
|
|
});
|
|
|
const host = _internal().ip.address();
|
|
|
const url = `${protocol}://${host}:${port}`;
|
|
|
|
|
|
// Extend the close method to ensure that we clean up the local info.
|
|
|
const originalClose = server.close.bind(server);
|
|
|
server.close = callback => {
|
|
|
return originalClose(err => {
|
|
|
_internal().ProjectSettings.setPackagerInfoAsync(projectRoot, {
|
|
|
webpackServerPort: null
|
|
|
}).finally(() => {
|
|
|
callback === null || callback === void 0 ? void 0 : callback(err);
|
|
|
webpackDevServerInstance = null;
|
|
|
webpackServerPort = null;
|
|
|
});
|
|
|
});
|
|
|
};
|
|
|
return {
|
|
|
server,
|
|
|
location: {
|
|
|
url,
|
|
|
port,
|
|
|
protocol,
|
|
|
host
|
|
|
},
|
|
|
// Match the native protocol.
|
|
|
messageSocket: {
|
|
|
broadcast: broadcastMessage
|
|
|
}
|
|
|
};
|
|
|
}
|
|
|
async function stopAsync(projectRoot) {
|
|
|
if (webpackDevServerInstance) {
|
|
|
await new Promise(res => {
|
|
|
if (webpackDevServerInstance) {
|
|
|
_internal().ProjectUtils.logInfo(projectRoot, WEBPACK_LOG_TAG, '\u203A Stopping Webpack server');
|
|
|
webpackDevServerInstance.close(res);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
async function openAsync(projectRoot, options) {
|
|
|
if (!webpackDevServerInstance) {
|
|
|
await startAsync(projectRoot, options);
|
|
|
}
|
|
|
await openProjectAsync(projectRoot);
|
|
|
}
|
|
|
async function compileWebAppAsync(projectRoot, compiler) {
|
|
|
// We generate the stats.json file in the webpack-config
|
|
|
const {
|
|
|
warnings
|
|
|
} = await new Promise((resolve, reject) => compiler.run((error, stats) => {
|
|
|
let messages;
|
|
|
if (error) {
|
|
|
if (!error.message) {
|
|
|
return reject(error);
|
|
|
}
|
|
|
messages = (0, _formatWebpackMessages().default)({
|
|
|
errors: [error.message],
|
|
|
warnings: [],
|
|
|
_showErrors: true,
|
|
|
_showWarnings: true
|
|
|
});
|
|
|
} else {
|
|
|
messages = (0, _formatWebpackMessages().default)(stats.toJson({
|
|
|
all: false,
|
|
|
warnings: true,
|
|
|
errors: true
|
|
|
}));
|
|
|
}
|
|
|
if (messages.errors.length) {
|
|
|
// Only keep the first error. Others are often indicative
|
|
|
// of the same problem, but confuse the reader with noise.
|
|
|
if (messages.errors.length > 1) {
|
|
|
messages.errors.length = 1;
|
|
|
}
|
|
|
return reject(new (_internal().XDLError)('WEBPACK_BUNDLE', messages.errors.join('\n\n')));
|
|
|
}
|
|
|
if (_getenv().default.boolish('EXPO_WEB_BUILD_STRICT', false) && _getenv().default.boolish('CI', false) && messages.warnings.length) {
|
|
|
_internal().ProjectUtils.logWarning(projectRoot, WEBPACK_LOG_TAG, _chalk().default.yellow('\nTreating warnings as errors because `process.env.CI = true` and `process.env.EXPO_WEB_BUILD_STRICT = true`. \n' + 'Most CI servers set it automatically.\n'));
|
|
|
return reject(new (_internal().XDLError)('WEBPACK_BUNDLE', messages.warnings.join('\n\n')));
|
|
|
}
|
|
|
resolve({
|
|
|
warnings: messages.warnings
|
|
|
});
|
|
|
}));
|
|
|
return {
|
|
|
warnings
|
|
|
};
|
|
|
}
|
|
|
async function bundleWebAppAsync(projectRoot, config) {
|
|
|
const compiler = (0, _webpack().default)(config);
|
|
|
try {
|
|
|
const {
|
|
|
warnings
|
|
|
} = await compileWebAppAsync(projectRoot, compiler);
|
|
|
if (warnings.length) {
|
|
|
_internal().ProjectUtils.logWarning(projectRoot, WEBPACK_LOG_TAG, _chalk().default.yellow('Compiled with warnings.\n'));
|
|
|
_internal().ProjectUtils.logWarning(projectRoot, WEBPACK_LOG_TAG, warnings.join('\n\n'));
|
|
|
} else {
|
|
|
_internal().ProjectUtils.logInfo(projectRoot, WEBPACK_LOG_TAG, _chalk().default.green('Compiled successfully.\n'));
|
|
|
}
|
|
|
} catch (error) {
|
|
|
_internal().ProjectUtils.logError(projectRoot, WEBPACK_LOG_TAG, _chalk().default.red('Failed to compile.\n'));
|
|
|
throw error;
|
|
|
}
|
|
|
}
|
|
|
async function bundleAsync(projectRoot, options) {
|
|
|
const fullOptions = transformCLIOptions({
|
|
|
...options
|
|
|
});
|
|
|
const env = await getWebpackConfigEnvFromBundlingOptionsAsync(projectRoot, {
|
|
|
...fullOptions,
|
|
|
// Force production
|
|
|
mode: 'production'
|
|
|
});
|
|
|
|
|
|
// @ts-ignore
|
|
|
if (typeof env.offline !== 'undefined') {
|
|
|
throw new Error('offline support must be added manually: https://expo.fyi/enabling-web-service-workers');
|
|
|
}
|
|
|
if (fullOptions.clear) {
|
|
|
await clearWebCacheAsync(projectRoot, env.mode);
|
|
|
}
|
|
|
const config = await loadConfigAsync(env);
|
|
|
await bundleWebAppAsync(projectRoot, config);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Get the URL for the running instance of Webpack dev server.
|
|
|
*
|
|
|
* @param projectRoot
|
|
|
*/
|
|
|
async function getUrlAsync(projectRoot) {
|
|
|
if (!webpackDevServerInstance) {
|
|
|
return null;
|
|
|
}
|
|
|
const host = _internal().ip.address();
|
|
|
const protocol = await getProtocolAsync(projectRoot);
|
|
|
return `${protocol}://${host}:${webpackServerPort}`;
|
|
|
}
|
|
|
async function getProtocolAsync(projectRoot) {
|
|
|
// TODO: Bacon: Handle when not in expo
|
|
|
const {
|
|
|
https
|
|
|
} = await _internal().ProjectSettings.readAsync(projectRoot);
|
|
|
return https === true ? 'https' : 'http';
|
|
|
}
|
|
|
async function getAvailablePortAsync(options) {
|
|
|
try {
|
|
|
const defaultPort = 'defaultPort' in options && options.defaultPort ? options.defaultPort : _internal().WebpackEnvironment.DEFAULT_PORT;
|
|
|
const port = await (0, _internal().choosePortAsync)(options.projectRoot, {
|
|
|
defaultPort,
|
|
|
host: 'host' in options && options.host ? options.host : _internal().WebpackEnvironment.HOST
|
|
|
});
|
|
|
if (!port) {
|
|
|
throw new Error(`Port ${defaultPort} not available.`);
|
|
|
}
|
|
|
return port;
|
|
|
} catch (error) {
|
|
|
throw new (_internal().XDLError)('NO_PORT_FOUND', error.message);
|
|
|
}
|
|
|
}
|
|
|
function setMode(mode) {
|
|
|
process.env.BABEL_ENV = mode;
|
|
|
process.env.NODE_ENV = mode;
|
|
|
}
|
|
|
function validateBoolOption(name, value, defaultValue) {
|
|
|
if (typeof value === 'undefined') {
|
|
|
value = defaultValue;
|
|
|
}
|
|
|
if (typeof value !== 'boolean') {
|
|
|
throw new (_internal().XDLError)('WEBPACK_INVALID_OPTION', `'${name}' option must be a boolean.`);
|
|
|
}
|
|
|
return value;
|
|
|
}
|
|
|
function transformCLIOptions(options) {
|
|
|
// Transform the CLI flags into more explicit values
|
|
|
return {
|
|
|
...options,
|
|
|
isImageEditingEnabled: options.pwa
|
|
|
};
|
|
|
}
|
|
|
async function applyOptionsToProjectSettingsAsync(projectRoot, options) {
|
|
|
const newSettings = {};
|
|
|
// Change settings before reading them
|
|
|
if (typeof options.https === 'boolean') {
|
|
|
newSettings.https = options.https;
|
|
|
}
|
|
|
if (Object.keys(newSettings).length) {
|
|
|
await _internal().ProjectSettings.setAsync(projectRoot, newSettings);
|
|
|
}
|
|
|
return await _internal().ProjectSettings.readAsync(projectRoot);
|
|
|
}
|
|
|
async function getWebpackConfigEnvFromBundlingOptionsAsync(projectRoot, options) {
|
|
|
const {
|
|
|
dev,
|
|
|
https
|
|
|
} = await applyOptionsToProjectSettingsAsync(projectRoot, options);
|
|
|
const mode = typeof options.mode === 'string' ? options.mode : dev ? 'development' : 'production';
|
|
|
const isImageEditingEnabled = validateBoolOption('isImageEditingEnabled', options.isImageEditingEnabled, true);
|
|
|
return {
|
|
|
projectRoot,
|
|
|
pwa: isImageEditingEnabled,
|
|
|
logger: _internal().ProjectUtils.getLogger(projectRoot),
|
|
|
isImageEditingEnabled,
|
|
|
mode,
|
|
|
https,
|
|
|
...(options.webpackEnv || {})
|
|
|
};
|
|
|
}
|
|
|
async function getSSLCertAsync({
|
|
|
name,
|
|
|
directory
|
|
|
}) {
|
|
|
console.log(_chalk().default.magenta`Ensuring auto SSL certificate is created (you might need to re-run with sudo)`);
|
|
|
try {
|
|
|
const result = await devcert().certificateFor(name);
|
|
|
if (result) {
|
|
|
const {
|
|
|
key,
|
|
|
cert
|
|
|
} = result;
|
|
|
const folder = path().join(directory, '.expo', 'web', 'development', 'ssl');
|
|
|
await _fsExtra().default.ensureDir(folder);
|
|
|
const keyPath = path().join(folder, `key-${name}.pem`);
|
|
|
await _fsExtra().default.writeFile(keyPath, key);
|
|
|
const certPath = path().join(folder, `cert-${name}.pem`);
|
|
|
await _fsExtra().default.writeFile(certPath, cert);
|
|
|
return {
|
|
|
keyPath,
|
|
|
certPath
|
|
|
};
|
|
|
}
|
|
|
return result;
|
|
|
} catch (error) {
|
|
|
console.log(`Error creating SSL certificates: ${error}`);
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
function applyEnvironmentVariables(config) {
|
|
|
// Use EXPO_DEBUG_WEB=true to enable debugging features for cases where the prod build
|
|
|
// has errors that aren't caught in development mode.
|
|
|
// Related: https://github.com/expo/expo-cli/issues/614
|
|
|
if (_internal().WebpackEnvironment.isDebugModeEnabled() && config.mode === 'production') {
|
|
|
console.log(_chalk().default.bgYellow.black('Bundling the project in debug mode.'));
|
|
|
const output = config.output || {};
|
|
|
const optimization = config.optimization || {};
|
|
|
|
|
|
// Enable line to line mapped mode for all/specified modules.
|
|
|
// Line to line mapped mode uses a simple SourceMap where each line of the generated source is mapped to the same line of the original source.
|
|
|
// It’s a performance optimization. Only use it if your performance need to be better and you are sure that input lines match which generated lines.
|
|
|
// true enables it for all modules (not recommended)
|
|
|
output.devtoolLineToLine = true;
|
|
|
|
|
|
// Add comments that describe the file import/exports.
|
|
|
// This will make it easier to debug.
|
|
|
output.pathinfo = true;
|
|
|
// Instead of numeric ids, give modules readable names for better debugging.
|
|
|
optimization.namedModules = true;
|
|
|
// Instead of numeric ids, give chunks readable names for better debugging.
|
|
|
optimization.namedChunks = true;
|
|
|
// Readable ids for better debugging.
|
|
|
// @ts-ignore Property 'moduleIds' does not exist.
|
|
|
optimization.moduleIds = 'named';
|
|
|
// if optimization.namedChunks is enabled optimization.chunkIds is set to 'named'.
|
|
|
// This will manually enable it just to be safe.
|
|
|
// @ts-ignore Property 'chunkIds' does not exist.
|
|
|
optimization.chunkIds = 'named';
|
|
|
if (optimization.splitChunks) {
|
|
|
optimization.splitChunks.name = true;
|
|
|
}
|
|
|
Object.assign(config, {
|
|
|
output,
|
|
|
optimization
|
|
|
});
|
|
|
}
|
|
|
return config;
|
|
|
}
|
|
|
async function loadConfigAsync(env, argv) {
|
|
|
setMode(env.mode);
|
|
|
// Check if the project has a webpack.config.js in the root.
|
|
|
const projectWebpackConfig = path().resolve(env.projectRoot, 'webpack.config.js');
|
|
|
let config;
|
|
|
if (_fsExtra().default.existsSync(projectWebpackConfig)) {
|
|
|
const webpackConfig = require(projectWebpackConfig);
|
|
|
if (typeof webpackConfig === 'function') {
|
|
|
config = await webpackConfig(env, argv);
|
|
|
} else {
|
|
|
config = webpackConfig;
|
|
|
}
|
|
|
} else {
|
|
|
// Fallback to the default expo webpack config.
|
|
|
const loadDefaultConfigAsync = require('@expo/webpack-config');
|
|
|
config = await loadDefaultConfigAsync(env, argv);
|
|
|
}
|
|
|
return applyEnvironmentVariables(config);
|
|
|
}
|
|
|
async function openProjectAsync(projectRoot) {
|
|
|
try {
|
|
|
const url = await _internal().UrlUtils.constructWebAppUrlAsync(projectRoot, {
|
|
|
hostType: 'localhost'
|
|
|
});
|
|
|
if (!url) {
|
|
|
throw new Error('Webpack Dev Server is not running');
|
|
|
}
|
|
|
(0, _betterOpn().default)(url);
|
|
|
return {
|
|
|
success: true,
|
|
|
url
|
|
|
};
|
|
|
} catch (e) {
|
|
|
_internal().Logger.global.error(`Couldn't start project on web: ${e.message}`);
|
|
|
return {
|
|
|
success: false,
|
|
|
error: e
|
|
|
};
|
|
|
}
|
|
|
}
|
|
|
//# sourceMappingURL=Webpack.js.map
|