gatsby
Version:
Blazing fast modern site generator for React
438 lines (432 loc) • 21.1 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.createGraphqlEngineBundle = createGraphqlEngineBundle;
var _isEqual2 = _interopRequireDefault(require("lodash/isEqual"));
var path = _interopRequireWildcard(require("path"));
var fs = _interopRequireWildcard(require("fs-extra"));
var _execa = _interopRequireDefault(require("execa"));
var _webpack = _interopRequireDefault(require("webpack"));
var _ConcatenatedModule = _interopRequireDefault(require("webpack/lib/optimize/ConcatenatedModule"));
var _package = require("gatsby/package.json");
var _printPlugins = require("./print-plugins");
var _module = _interopRequireDefault(require("module"));
var _webpackLogging = require("../../utils/webpack/plugins/webpack-logging");
var _webpackAssetRelocatorLoader = require("@vercel/webpack-asset-relocator-loader");
var nodeApis = _interopRequireWildcard(require("../../utils/api-node-docs"));
var _redux = require("../../redux");
var _path2 = require("gatsby-core-utils/path");
var _enginesHelpers = require("../../utils/engines-helpers");
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; }
/* eslint-disable @typescript-eslint/naming-convention */
const extensions = [`.mjs`, `.js`, `.json`, `.node`, `.ts`, `.tsx`];
const outputDir = path.posix.join((0, _path2.slash)(process.cwd()), `.cache`, `query-engine`);
const cacheLocation = path.posix.join((0, _path2.slash)(process.cwd()), `.cache`, `webpack`, `query-engine`);
function getApisToRemoveForQueryEngine() {
const apisToKeep = new Set(_printPlugins.schemaCustomizationAPIs);
apisToKeep.add(`onPluginInit`);
const apisToRemove = Object.keys(nodeApis).filter(api => !apisToKeep.has(api));
return apisToRemove;
}
const getInternalPackagesCacheDir = functionsTarget => path.posix.join((0, _path2.slash)(process.cwd()), `.cache`, `internal-packages`, `${functionsTarget.platform}-${functionsTarget.arch}`);
// Create a directory and JS module where we install internally used packages
const createInternalPackagesCacheDir = async functionsTarget => {
const cacheDir = getInternalPackagesCacheDir(functionsTarget);
await fs.ensureDir(cacheDir);
const packageJsonPath = path.join(cacheDir, `package.json`);
if (!fs.existsSync(packageJsonPath)) {
await fs.emptyDir(cacheDir);
await fs.outputJson(packageJsonPath, {
name: `gatsby-internal-packages`,
description: `This directory contains internal packages installed by Gatsby used to comply with the current platform requirements`,
version: `1.0.0`,
private: true,
author: `Gatsby`,
license: `MIT`,
functionsTarget
});
}
};
function getLMDBBinaryFromSiteLocation(lmdbPackageName, version, functionsTarget) {
// Read lmdb's package.json, go through its optional depedencies and validate if there's a prebuilt lmdb module with a compatible binary to our platform and arch
let packageJson;
try {
const modulePath = path.dirname((0, _path2.slash)(require.resolve(`lmdb`))).replace(`/dist`, ``);
const packageJsonPath = path.join(modulePath, `package.json`);
packageJson = JSON.parse(fs.readFileSync(packageJsonPath, `utf-8`));
} catch (e) {
// If we fail to read lmdb's package.json there's bigger problems here so just skip installation
return undefined;
}
// If there's no lmdb prebuilt package for our arch/platform listed as optional dep no point in trying to install it
const {
optionalDependencies = {}
} = packageJson;
if (!Object.keys(optionalDependencies).find(p => p === lmdbPackageName)) {
throw new Error(`Target platform/arch for functions execution (${functionsTarget.platform}/${functionsTarget.arch}) is not supported.`);
}
return getPackageLocationFromRequireContext((0, _path2.slash)(require.resolve(`lmdb`)), lmdbPackageName, version);
}
function getPackageLocationFromRequireContext(location, packageName, packageVersion) {
try {
const requireId = `${packageName}/package.json`;
const locationRequire = _module.default.createRequire(location);
const packageJsonLocation = (0, _path2.slash)(locationRequire.resolve(requireId));
if (packageVersion) {
// delete locationRequire.cache[requireId]
const {
version
} = JSON.parse(fs.readFileSync(packageJsonLocation, `utf-8`));
if (packageVersion !== version) {
return undefined;
}
}
return path.dirname(packageJsonLocation);
} catch (e) {
return undefined;
}
}
function checkIfInstalledInInternalPackagesCache(packageStatus, functionsTarget) {
const cacheDir = getInternalPackagesCacheDir(functionsTarget);
const packageLocationFromInternalPackageCache = getPackageLocationFromRequireContext(path.posix.join(cacheDir, `:internal:`), packageStatus.packageName, packageStatus.packageVersion);
if (packageLocationFromInternalPackageCache && !path.posix.relative(cacheDir, packageLocationFromInternalPackageCache).startsWith(`..`)) {
return {
...packageStatus,
needToInstall: false,
packageLocation: packageLocationFromInternalPackageCache
};
}
return {
...packageStatus,
needToInstall: true
};
}
// Install lmdb's native system module under our internal cache if we detect the current installation
// isn't using the pre-build binaries
function checkIfNeedToInstallMissingLmdb(functionsTarget) {
// lmdb module with prebuilt binaries for target platform
const lmdbPackageName = `@lmdb/lmdb-${functionsTarget.platform}-${functionsTarget.arch}`;
const lmdbBinaryFromSiteLocation = getLMDBBinaryFromSiteLocation(lmdbPackageName, _package.dependencies.lmdb, functionsTarget);
const sharedPackageStatus = {
needToInstall: true,
packageName: lmdbPackageName,
packageVersion: _package.dependencies.lmdb
};
if (lmdbBinaryFromSiteLocation) {
return {
...sharedPackageStatus,
needToInstall: false,
packageLocation: lmdbBinaryFromSiteLocation
};
}
return checkIfInstalledInInternalPackagesCache(sharedPackageStatus, functionsTarget);
}
function checkIfNeedToInstallMissingSharp(functionsTarget, currentTarget) {
try {
// check if shapr is resolvable
const {
version: sharpVersion
} = require(`sharp/package.json`);
if ((0, _isEqual2.default)(functionsTarget, currentTarget)) {
return undefined;
}
return checkIfInstalledInInternalPackagesCache({
needToInstall: true,
packageName: `sharp`,
packageVersion: sharpVersion
}, functionsTarget);
} catch (e) {
return undefined;
}
}
async function installMissing(packages, functionsTarget) {
function shouldInstall(p) {
return Boolean(p === null || p === void 0 ? void 0 : p.needToInstall);
}
const packagesToInstall = packages.filter(shouldInstall);
if (packagesToInstall.length === 0) {
return packages;
}
await createInternalPackagesCacheDir(functionsTarget);
const cacheDir = getInternalPackagesCacheDir(functionsTarget);
const options = {
stderr: `inherit`,
cwd: cacheDir,
env: {
npm_config_arch: functionsTarget.arch,
npm_config_platform: functionsTarget.platform
}
};
const npmAdditionalCliArgs = [`--no-progress`, `--no-audit`, `--no-fund`, `--loglevel`, `error`, `--color`, `always`, `--legacy-peer-deps`, `--save-exact`,
// target platform might be different than current and force allows us to install it
`--force`];
await (0, _execa.default)(`npm`, [`install`, ...npmAdditionalCliArgs, ...packagesToInstall.map(p => `${p.packageName}@${p.packageVersion}`)], options);
return packages.map(info => info ? info.needToInstall ? {
...info,
needToInstall: false,
packageLocation: path.posix.join(cacheDir, `node_modules`, info.packageName)
} : info : undefined);
}
async function createGraphqlEngineBundle(rootDir, reporter, isVerbose) {
var _state$config$pathPre, _process$env$GATSBY_W;
const state = _redux.store.getState();
const pathPrefix = state.program.prefixPaths ? (_state$config$pathPre = state.config.pathPrefix) !== null && _state$config$pathPre !== void 0 ? _state$config$pathPre : `` : ``;
const schemaSnapshotString = await fs.readFile(path.join(rootDir, `.cache`, `schema.gql`), `utf-8`);
await (0, _printPlugins.printQueryEnginePlugins)();
const assetRelocatorUseEntry = {
loader: require.resolve(`@vercel/webpack-asset-relocator-loader`),
options: {
outputAssetBase: `assets`
}
};
const gatsbyPluginTSRequire = _module.default.createRequire(require.resolve(`gatsby-plugin-typescript`));
const currentTarget = (0, _enginesHelpers.getCurrentPlatformAndTarget)();
const functionsTarget = (0, _enginesHelpers.getFunctionsTargetPlatformAndTarget)();
const dynamicAliases = {};
let forcedLmdbBinaryModule = undefined;
// we need to make sure we have internal packages cache directory setup for current lambda target
// before we attempt to check if we can reuse those packages
await createInternalPackagesCacheDir(functionsTarget);
const [lmdbPackageInfo, sharpPackageInfo] = await installMissing([checkIfNeedToInstallMissingLmdb(functionsTarget), checkIfNeedToInstallMissingSharp(functionsTarget, currentTarget)], functionsTarget);
if (!lmdbPackageInfo) {
throw new Error(`Failed to find required LMDB binary`);
} else if (functionsTarget.platform === `linux`) {
// function execution platform is primarily linux, which is tested the most, so we only force that specific binary
// to not cause untested code paths
if (lmdbPackageInfo.needToInstall) {
throw new Error(`Failed to locate or install LMDB binary for functions execution platform/arch (${functionsTarget.platform}/${functionsTarget.arch})`);
}
forcedLmdbBinaryModule = `${lmdbPackageInfo.packageLocation}/node.abi83.glibc.node`;
}
if (sharpPackageInfo) {
if (sharpPackageInfo.needToInstall) {
throw new Error(`Failed to locate or install Sharp binary for functions execution platform/arch (${functionsTarget.platform}/${functionsTarget.arch})`);
}
dynamicAliases[`sharp$`] = sharpPackageInfo.packageLocation;
}
const compiler = (0, _webpack.default)({
name: `Query Engine`,
// mode: `production`,
mode: `none`,
entry: path.join(__dirname, `entry.js`),
output: {
path: outputDir,
filename: `index.js`,
libraryTarget: `commonjs`
},
target: `node`,
externalsPresets: {
node: false
},
cache: {
type: `filesystem`,
name: `graphql-engine`,
cacheLocation,
buildDependencies: {
config: [__filename]
},
version: JSON.stringify(functionsTarget)
},
// those are required in some runtime paths, but we don't need them
externals: [`cbor-x`,
// optional dep of lmdb-store, but we are using `msgpack` (default) encoding, so we don't need it
`electron`,
// :shrug: `got` seems to have electron specific code path
_module.default.builtinModules.reduce((acc, builtinModule) => {
if (builtinModule === `fs`) {
acc[builtinModule] = `global _actualFsWrapper`;
acc[`node:${builtinModule}`] = `global _actualFsWrapper`;
} else {
acc[builtinModule] = `commonjs ${builtinModule}`;
acc[`node:${builtinModule}`] = `commonjs ${builtinModule}`;
}
return acc;
}, {})],
module: {
rules: [{
oneOf: [{
// specific set of loaders for sharp
test: /node_modules[/\\]sharp[/\\].*\.[cm]?js$/,
// it is recommended for Node builds to turn off AMD support
parser: {
amd: false
},
use: [assetRelocatorUseEntry, {
loader: require.resolve(`./sharp-bundling-patch`)
}]
}, {
// specific set of loaders for LMBD - our custom patch to massage lmdb to work with relocator -> relocator
test: /node_modules[/\\]lmdb[/\\].*\.[cm]?js/,
// it is recommended for Node builds to turn off AMD support
parser: {
amd: false
},
use: [assetRelocatorUseEntry, {
loader: require.resolve(`./lmdb-bundling-patch`),
options: {
forcedBinaryModule: forcedLmdbBinaryModule
}
}]
}, {
// specific set of loaders for gatsby-node files - our babel transform that removes lifecycles not needed for engine -> relocator
test: /gatsby-node\.(cjs|mjs|js|ts)$/,
// it is recommended for Node builds to turn off AMD support
parser: {
amd: false
},
use: [assetRelocatorUseEntry, {
loader: require.resolve(`../../utils/webpack/loaders/webpack-remove-exports-loader`),
options: {
remove: getApisToRemoveForQueryEngine(),
jsx: false
}
}]
}, {
// generic loader for all other cases than lmdb or gatsby-node - we don't do anything special other than using relocator on it
// For node binary relocations, include ".node" files as well here
test: /\.(cjs|mjs|js|ts|node)$/,
// it is recommended for Node builds to turn off AMD support
parser: {
amd: false
},
use: assetRelocatorUseEntry
}]
}, {
test: /\.ts$/,
exclude: /node_modules/,
use: {
loader: require.resolve(`babel-loader`),
options: {
presets: [gatsbyPluginTSRequire.resolve(`@babel/preset-typescript`)]
}
}
}, {
test: /\.m?js$/,
type: `javascript/auto`,
resolve: {
byDependency: {
esm: {
fullySpecified: false
}
}
}
}, {
test: /\.txt/,
type: `asset/resource`
}, {
test: /\.(graphqls?|gqls?)$/,
use: {
loader: require.resolve(`graphql-tag/loader`)
}
}]
},
resolve: {
extensions,
alias: {
...dynamicAliases,
".cache": process.cwd() + `/.cache/`,
[require.resolve(`gatsby-cli/lib/reporter/loggers/ink/index.js`)]: false,
inquirer: false,
// only load one version of lmdb
lmdb: require.resolve(`lmdb`),
"ts-node": require.resolve(`./shims/ts-node`),
"gatsby-sharp$": require.resolve(`./shims/gatsby-sharp`),
"graphql-import-node$": require.resolve(`./shims/no-op-module`),
"graphql-import-node/register$": require.resolve(`./shims/no-op-module`),
"babel-runtime/helpers/asyncToGenerator": require.resolve(`./shims/no-op-module`) // undeclared dep of yurnalist (but used in code path we don't use)
}
},
plugins: [new _webpack.default.EnvironmentPlugin([`GATSBY_CLOUD_IMAGE_CDN`]), new _webpack.default.DefinePlugin({
"process.env.GATSBY_SKIP_WRITING_SCHEMA_TO_FILE": `true`,
"process.env.NODE_ENV": JSON.stringify(`production`),
SCHEMA_SNAPSHOT: JSON.stringify(schemaSnapshotString),
PATH_PREFIX: JSON.stringify(pathPrefix),
"process.env.GATSBY_LOGGER": JSON.stringify(`yurnalist`),
"process.env.GATSBY_SLICES": JSON.stringify(!!process.env.GATSBY_SLICES),
"process.env.GATSBY_FUNCTIONS_PLATFORM": JSON.stringify(functionsTarget.platform),
"process.env.GATSBY_FUNCTIONS_ARCH": JSON.stringify(functionsTarget.arch)
}), ((_process$env$GATSBY_W = process.env.GATSBY_WEBPACK_LOGGING) === null || _process$env$GATSBY_W === void 0 ? void 0 : _process$env$GATSBY_W.includes(`query-engine`)) && new _webpackLogging.WebpackLoggingPlugin(rootDir, reporter, isVerbose)].filter(Boolean)
});
return new Promise((resolve, reject) => {
compiler.run(async (err, stats) => {
function getResourcePath(webpackModule) {
if (webpackModule && !(webpackModule instanceof _ConcatenatedModule.default)) {
return webpackModule.resource;
}
if (webpackModule !== null && webpackModule !== void 0 && webpackModule.modules) {
// ConcatenatedModule is a collection of modules so we have to go deeper to actually get a path,
// at this point we won't know which one so we just grab first module here
const [firstSubModule] = webpackModule.modules;
return getResourcePath(firstSubModule);
}
return undefined;
}
function iterateModules(webpackModules, compilation) {
for (const webpackModule of webpackModules) {
if (webpackModule instanceof _ConcatenatedModule.default) {
iterateModules(webpackModule.modules, compilation);
} else {
const resourcePath = getResourcePath(webpackModule);
if (resourcePath !== null && resourcePath !== void 0 && resourcePath.includes(`ts-node`)) {
const importedBy = getResourcePath(compilation.moduleGraph.getIssuer(webpackModule));
const structuredError = {
id: `98011`,
context: {
package: `ts-node`,
importedBy,
advisory: `Gatsby is supporting TypeScript natively (see https://gatsby.dev/typescript). "ts-node" might not be needed anymore at all, consider removing it.`
}
};
throw structuredError;
}
}
}
}
try {
if (stats !== null && stats !== void 0 && stats.compilation.modules) {
iterateModules(stats.compilation.modules, stats.compilation);
}
if (!(0, _isEqual2.default)(functionsTarget, currentTarget)) {
const binaryFixingPromises = [];
// sigh - emitAsset used by relocator seems to corrupt binaries
// resulting in "ELF file's phentsize not the expected size" errors
// - see size diff
// > find . -name node.abi83.glibc.node
// ./.cache/internal-packages/node_modules/@lmdb/lmdb-linux-x64/node.abi83.glibc.node
// ./.cache/query-engine/assets/node.abi83.glibc.node
// > ls -al ./.cache/query-engine/assets/node.abi83.glibc.node
// -rw-r--r-- 1 misiek 197121 1285429 Mar 14 11:36 ./.cache/query-engine/assets/node.abi83.glibc.node
// > ls -al ./.cache/internal-packages/node_modules/@lmdb/lmdb-linux-x64/node.abi83.glibc.node
// -rw-r--r-- 1 misiek 197121 693544 Mar 14 11:35 ./.cache/internal-packages/node_modules/@lmdb/lmdb-linux-x64/node.abi83.glibc.node
// so this tries to fix it by straight copying it over
for (const asset of ((_stats$compilation$as = stats === null || stats === void 0 ? void 0 : (_stats$compilation = stats.compilation) === null || _stats$compilation === void 0 ? void 0 : _stats$compilation.assetsInfo) !== null && _stats$compilation$as !== void 0 ? _stats$compilation$as : new Map()).keys()) {
var _stats$compilation$as, _stats$compilation;
if (asset !== null && asset !== void 0 && asset.endsWith(`.node`)) {
const targetRelPath = path.posix.relative(`assets`, asset);
const assetMeta = (0, _webpackAssetRelocatorLoader.getAssetMeta)(targetRelPath, stats === null || stats === void 0 ? void 0 : stats.compilation);
const sourcePath = assetMeta === null || assetMeta === void 0 ? void 0 : assetMeta.path;
if (sourcePath) {
const dist = path.join(outputDir, asset);
binaryFixingPromises.push(fs.copyFile(sourcePath, dist));
}
}
}
await Promise.all(binaryFixingPromises);
}
compiler.close(closeErr => {
if (err) {
return reject(err);
}
if (closeErr) {
return reject(closeErr);
}
return resolve(stats === null || stats === void 0 ? void 0 : stats.compilation);
});
} catch (e) {
reject(e);
}
});
});
}
//# sourceMappingURL=bundle-webpack.js.map
;