diff --git a/docs/install.md b/docs/install.md index 31a22acf..7b96343d 100644 --- a/docs/install.md +++ b/docs/install.md @@ -118,11 +118,11 @@ When building your deployment package on a machine that differs from the target you will need to install either `@img/sharp-linux-x64` or `@img/sharp-linux-arm64` package. ```sh -npm install --os=linux --cpu=x64 +npm install --os=linux --cpu=x64 sharp ``` ```sh -npm install --os=linux --cpu=arm64 +npm install --os=linux --cpu=arm64 sharp ``` When using npm 9 or earlier, this can be achieved using the following: diff --git a/lib/sharp.js b/lib/sharp.js index d4eaae07..85c3d593 100644 --- a/lib/sharp.js +++ b/lib/sharp.js @@ -9,62 +9,71 @@ const { familySync, versionSync } = require('detect-libc'); const { runtimePlatformArch, prebuiltPlatforms, minimumLibvipsVersion } = require('./libvips'); const runtimePlatform = runtimePlatformArch(); -const [isLinux, isMacOs, isWindows] = ['linux', 'darwin', 'win32'].map(os => runtimePlatform.startsWith(os)); -/* istanbul ignore next */ -try { - // Check for local build - module.exports = require(`../src/build/Release/sharp-${runtimePlatform}.node`); -} catch (errLocal) { +const paths = [ + `../src/build/Release/sharp-${runtimePlatform}.node`, + `@img/sharp-${runtimePlatform}/sharp.node` +]; + +const errors = []; +for (const path of paths) { try { - // Check for runtime package - module.exports = require(`@img/sharp-${runtimePlatform}/sharp.node`); - } catch (errPackage) { - const help = ['Could not load the "sharp" module at runtime']; - if (errLocal.code !== 'MODULE_NOT_FOUND') { - help.push(`${errLocal.code}: ${errLocal.message}`); - } - if (errPackage.code !== 'MODULE_NOT_FOUND') { - help.push(`${errPackage.code}: ${errPackage.message}`); - } - help.push('Possible solutions:'); - // Common error messages - if (prebuiltPlatforms.includes(runtimePlatform)) { - const [os, cpu] = runtimePlatform.split('-'); - help.push('- Add an explicit dependency for the runtime platform:'); - help.push(` npm install --os=${os} --cpu=${cpu} sharp`); - help.push(' or'); - help.push(` npm install --force @img/sharp-${runtimePlatform}`); - } else { - help.push(`- The ${runtimePlatform} platform requires manual installation of libvips >= ${minimumLibvipsVersion}`); - } - if (isLinux && /symbol not found/i.test(errPackage)) { - try { - const { engines } = require(`@img/sharp-libvips-${runtimePlatform}/package`); - const libcFound = `${familySync()} ${versionSync()}`; - const libcRequires = `${engines.musl ? 'musl' : 'glibc'} ${engines.musl || engines.glibc}`; - help.push('- Update your OS:'); - help.push(` Found ${libcFound}`); - help.push(` Requires ${libcRequires}`); - } catch (errEngines) {} - } - if (isMacOs && /Incompatible library version/.test(errLocal.message)) { - help.push('- Update Homebrew:'); - help.push(' brew update && brew upgrade vips'); - } - if (errPackage.code === 'ERR_DLOPEN_DISABLED') { - help.push('- Run Node.js without using the --no-addons flag'); - } - if (process.versions.pnp) { - help.push('- Use a supported yarn linker, either pnpm or node-modules:'); - help.push(' yarn config set nodeLinker node-modules'); - } - // Link to installation docs - if (isWindows && /The specified procedure could not be found/.test(errPackage.message)) { - help.push('- Using the canvas package on Windows? See https://sharp.pixelplumbing.com/install#canvas-and-windows'); - } else { - help.push('- Consult the installation documentation: https://sharp.pixelplumbing.com/install'); - } - throw new Error(help.join('\n')); + module.exports = require(path); + break; + } catch (err) { + /* istanbul ignore next */ + errors.push(err); } } + +/* istanbul ignore next */ +if (!module.exports) { + const [isLinux, isMacOs, isWindows] = ['linux', 'darwin', 'win32'].map(os => runtimePlatform.startsWith(os)); + + const help = [`Could not load the "sharp" module using the ${runtimePlatform} runtime`]; + errors.forEach(err => { + if (err.code !== 'MODULE_NOT_FOUND') { + help.push(`${err.code}: ${err.message}`); + } + }); + const messages = errors.map(err => err.message).join(' '); + help.push('Possible solutions:'); + // Common error messages + if (prebuiltPlatforms.includes(runtimePlatform)) { + const [os, cpu] = runtimePlatform.split('-'); + help.push('- Add platform-specific dependencies:'); + help.push(` npm install --os=${os} --cpu=${cpu} sharp`); + help.push(' or'); + help.push(` npm install --force @img/sharp-${runtimePlatform}`); + } else { + help.push(`- Manually install libvips >= ${minimumLibvipsVersion}`); + } + if (isLinux && /symbol not found/i.test(messages)) { + try { + const { engines } = require(`@img/sharp-libvips-${runtimePlatform}/package`); + const libcFound = `${familySync()} ${versionSync()}`; + const libcRequires = `${engines.musl ? 'musl' : 'glibc'} ${engines.musl || engines.glibc}`; + help.push('- Update your OS:'); + help.push(` Found ${libcFound}`); + help.push(` Requires ${libcRequires}`); + } catch (errEngines) {} + } + if (isMacOs && /Incompatible library version/.test(messages)) { + help.push('- Update Homebrew:'); + help.push(' brew update && brew upgrade vips'); + } + if (errors.some(err => err.code === 'ERR_DLOPEN_DISABLED')) { + help.push('- Run Node.js without using the --no-addons flag'); + } + if (process.versions.pnp) { + help.push('- Use a supported yarn linker, either pnpm or node-modules:'); + help.push(' yarn config set nodeLinker node-modules'); + } + // Link to installation docs + if (isWindows && /The specified procedure could not be found/.test(messages)) { + help.push('- Using the canvas package on Windows? See https://sharp.pixelplumbing.com/install#canvas-and-windows'); + } else { + help.push('- Consult the installation documentation: https://sharp.pixelplumbing.com/install'); + } + throw new Error(help.join('\n')); +} diff --git a/package.json b/package.json index d775ddae..29916250 100644 --- a/package.json +++ b/package.json @@ -164,7 +164,7 @@ "@img/sharp-libvips-win32-ia32": "0.0.3", "@img/sharp-libvips-win32-x64": "0.0.3", "@types/node": "*", - "async": "^3.2.4", + "async": "^3.2.5", "cc": "^3.0.1", "exif-reader": "^2.0.0", "extract-zip": "^2.0.1",