Files
flipper/desktop/pkg-lib/src/runBuild.ts
Pascal Hartig 0e1f8e45ec Refactor out strip source map fn
Summary: Remove the duplicate function and centralise it as nikoant suggested.

Reviewed By: fabiomassimo

Differential Revision: D29548480

fbshipit-source-id: 3e931cc88198415017c557c6b7c81cb35c3f22c9
2021-07-05 06:37:09 -07:00

124 lines
3.6 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import Metro from 'metro';
import getWatchFolders from './getWatchFolders';
import path from 'path';
import fs from 'fs-extra';
import {getInstalledPluginDetails} from 'flipper-plugin-lib';
import {FileStore} from 'metro-cache';
import stripSourceMapComment from './stripSourceMap';
import os from 'os';
let metroDir: string | undefined;
const metroDirPromise = getMetroDir().then((dir) => (metroDir = dir));
// We need to include metro-runtime to the watched folders list because it contains modules which are included into the final bundle.
async function getMetroDir() {
let dir = __dirname;
while (true) {
const dirToCheck = path.join(dir, 'node_modules', 'metro-runtime');
if (await fs.pathExists(dirToCheck)) return dirToCheck;
const nextDir = path.dirname(dir);
if (!nextDir || nextDir === '' || nextDir === dir) {
break;
}
dir = nextDir;
}
return __dirname;
}
type Options = {
sourceMapPath?: string | undefined;
};
export default async function bundlePlugin(
pluginDir: string,
dev: boolean,
options?: Options,
) {
const stat = await fs.lstat(pluginDir);
if (!stat.isDirectory()) {
throw new Error(`Plugin source ${pluginDir} is not a directory.`);
}
const packageJsonPath = path.join(pluginDir, 'package.json');
if (!(await fs.pathExists(packageJsonPath))) {
throw new Error(
`package.json is not found in plugin source directory ${pluginDir}.`,
);
}
const plugin = await getInstalledPluginDetails(pluginDir);
const entry = plugin.source;
const out = path.resolve(pluginDir, plugin.main);
await fs.ensureDir(path.dirname(out));
const baseConfig = await Metro.loadConfig();
const config = Object.assign({}, baseConfig, {
reporter: {update: () => {}},
projectRoot: pluginDir,
watchFolders: [metroDir || (await metroDirPromise)].concat(
await getWatchFolders(pluginDir),
),
serializer: {
...baseConfig.serializer,
getRunModuleStatement: (moduleID: string) =>
`module.exports = global.__r(${moduleID});`,
},
transformer: {
...baseConfig.transformer,
babelTransformerPath: require.resolve('flipper-babel-transformer'),
minifierPath: require.resolve('metro-minify-terser'),
minifierConfig: {
// see: https://www.npmjs.com/package/terser
keep_fnames: true,
module: true,
warnings: true,
mangle: false,
compress: false,
},
},
resolver: {
...baseConfig.resolver,
resolverMainFields: ['flipperBundlerEntry', 'module', 'main'],
sourceExts: ['js', 'jsx', 'ts', 'tsx', 'json', 'mjs', 'cjs'],
blacklistRE: /\.native\.js$/,
},
cacheStores: [
new FileStore({
root:
process.env.FLIPPER_METRO_CACHE ??
path.join(os.tmpdir(), 'metro-cache'),
}),
],
});
const sourceMapUrl = out.replace(/\.js$/, '.map');
const sourceMap = dev || !!options?.sourceMapPath;
await Metro.runBuild(config, {
dev,
sourceMap,
sourceMapUrl,
minify: !dev,
inlineSourceMap: dev,
resetCache: false,
entry,
out,
});
if (sourceMap && !dev) {
await stripSourceMapComment(out);
}
if (
options?.sourceMapPath &&
path.resolve(options.sourceMapPath) !== path.resolve(sourceMapUrl)
) {
console.log(`Moving plugin sourcemap to ${options.sourceMapPath}`);
await fs.ensureDir(path.dirname(options.sourceMapPath));
await fs.move(sourceMapUrl, options.sourceMapPath, {overwrite: true});
}
}