Don't install Ruby or Python dependencies unnecessarily (#7084)

* Don't install Ruby or Python dependencies unnecessarily

* Less repeated code

* Cleaner code
This commit is contained in:
Leo Lamprecht
2021-11-30 14:36:27 +01:00
committed by GitHub
parent edb5eead81
commit abd9f019f1
5 changed files with 47 additions and 11 deletions

View File

@@ -52,6 +52,9 @@ export function convertRuntimeToPlugin(
includeFiles: config.includeFiles,
excludeFiles: config.excludeFiles,
},
meta: {
avoidTopLevelInstall: true,
},
});
pages[entrypoint] = {

View File

@@ -58,6 +58,7 @@ export interface Meta {
filesRemoved?: string[];
env?: Env;
buildEnv?: Env;
avoidTopLevelInstall?: boolean;
}
export interface AnalyzeOptions {

View File

@@ -1,3 +1,4 @@
import { relative, basename } from 'path';
import execa from 'execa';
import { Meta, debug } from '@vercel/build-utils';
@@ -135,6 +136,18 @@ export async function installRequirementsFile({
meta,
args = [],
}: InstallRequirementsFileArg) {
const fileAtRoot = relative(workPath, filePath) === basename(filePath);
// If the `requirements.txt` file is located in the Root Directory of the project and
// the new File System API is used (`avoidTopLevelInstall`), the Install Command
// will have already installed its dependencies, so we don't need to do it again.
if (meta.avoidTopLevelInstall && fileAtRoot) {
debug(
`Skipping requirements file installation, already installed by Install Command`
);
return;
}
if (
meta.isDev &&
(await areRequirementsInstalled(pythonPath, filePath, workPath))

View File

@@ -1,4 +1,4 @@
import { join, dirname } from 'path';
import { join, dirname, relative } from 'path';
import execa from 'execa';
import {
ensureDir,
@@ -85,10 +85,12 @@ export async function build({
}: BuildOptions) {
await download(files, workPath, meta);
const entrypointFsDirname = join(workPath, dirname(entrypoint));
const gemfileName = 'Gemfile';
const gemfilePath = await walkParentDirs({
base: workPath,
start: entrypointFsDirname,
filename: 'Gemfile',
filename: gemfileName,
});
const gemfileContents = gemfilePath
? await readFile(gemfilePath, 'utf8')
@@ -130,6 +132,14 @@ export async function build({
'did not find a vendor directory but found a Gemfile, bundling gems...'
);
const fileAtRoot = relative(workPath, gemfilePath) === gemfileName;
// If the `Gemfile` is located in the Root Directory of the project and
// the new File System API is used (`avoidTopLevelInstall`), the Install Command
// will have already installed its dependencies, so we don't need to do it again.
if (meta.avoidTopLevelInstall && fileAtRoot) {
debug('Skipping `bundle install` — already handled by Install Command');
} else {
// try installing. this won't work if native extesions are required.
// if that's the case, gems should be vendored locally before deploying.
try {
@@ -141,6 +151,7 @@ export async function build({
throw err;
}
}
}
} else {
debug('found vendor directory, skipping "bundle install"...');
}

View File

@@ -61,6 +61,14 @@ function getRubyPath(meta: Meta, gemfileContents: string) {
// process.env.GEM_HOME), and returns
// the absolute path to it
export async function installBundler(meta: Meta, gemfileContents: string) {
// If the new File System API is used (`avoidTopLevelInstall`), the Install Command
// will have already installed the dependencies, so we don't need to do it again.
if (meta.avoidTopLevelInstall) {
debug(
`Skipping bundler installation, already installed by Install Command`
);
}
const { gemHome, rubyPath, gemPath, vendorPath, runtime } = getRubyPath(
meta,
gemfileContents