Sapper: Importing @sapper/app from External Component

Created on 2 May 2019  路  7Comments  路  Source: sveltejs/sapper

I've got some external components that I'm importing (after sorting out #637) that import @sapper/app, but my components can't seem to find it.

internal/modules/cjs/loader.js:584
    throw err;
    ^

Error: Cannot find module '@sapper/app'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:582:15)
    at Function.Module._load (internal/modules/cjs/loader.js:508:25)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at Object.<anonymous> (/Users/evan/Code/prepaid/smartrewards/csr/__sapper__/dev/server/chunk-1ca46139.js:5:11)
    at Module._compile (internal/modules/cjs/loader.js:701:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
    at Module.load (internal/modules/cjs/loader.js:600:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
    at Function.Module._load (internal/modules/cjs/loader.js:531:3)

Since I'm importing the component into the Sapper application it seems like @sapper/app should be available, though it's in the src directory. I'm using pnpm which may affect the situation some, but I'm curious if you've run into this problem before.

Thank you!

Most helpful comment

We have the same issue when trying to use Ava or Jest for testing our Svelte/Sapper app. Not using external components explicitly, but perhaps the testing libraries interpret them as such.

Does anyone have experience with a workaround for this error for Jest or similar?

All 7 comments

Is it still an issue if you use npm or yarn?

A component in an external module at node_modules/something/... is not going to be able to find something at src/node_modules/@sapper/.... That's just how the Node module resolution algorithm works.

I don't think having an external module with components that can import stuff in this special @sapper directory is something we're really going to want to support anyway. Besides the technical hurdles, this would also tie components to particular versions of Sapper.

What you could do instead (and what I think is the preferred way to go about this anyway) is to just explicitly pass the data you want these components to have through props.

@Conduitry, got it, I guess I didn't realize @sapper wouldn't be available to external modules. You're right that it ties components to a version of Sapper, but I figured I'd use peer dependencies to keep them in sync. Still, I like your solution of passing whatever's needed in as a prop. Thanks!

I ran to the same problem as well when trying to deploy my Sapper app into gCloud CloudRun.. Weird though, when I deploy the app to docker it runs well. When deploying it to the cloud I get the same error message mentioned

We have the same issue when trying to use Ava or Jest for testing our Svelte/Sapper app. Not using external components explicitly, but perhaps the testing libraries interpret them as such.

Does anyone have experience with a workaround for this error for Jest or similar?

+1 for having this issue in Jest. Would love to hear an answer on this!

@jhwheeler @KevinConti
Edit: Forgot to mention that it's definitely due to the fact that Jest doesn't detect .mjs extensions. It took about 10 good hours of hunting and experimenting to figure out this solution. It's a bit dirty, but it's functional and not hacky.
Jest doesn't support ESM out of the box sadly. However, here's the work around I used to achieve testing end to end:

// babel.config.js
module.exports = {
    presets: [
        [ '@babel/preset-env', {
            targets: '> 0.25%, not dead',
        } ],
        '@babel/preset-typescript'
    ],
    plugins: [
        'babel-plugin-transform-typescript-metadata',
        [ '@babel/plugin-proposal-decorators', {
            legacy: true,
        } ],
        [ '@babel/plugin-proposal-class-properties', {
            loose: true,
        } ],
        '@babel/plugin-transform-runtime'
    ],
};
// tsconfig.json
{
    "include": [ "src/**/*" ],
    "exclude": [ "node_modules/*" ],
    "compilerOptions": {
        "module": "esnext",
        "moduleResolution": "node",
        "target": "esnext",
        "typeRoots": [ "typings", "node_modules/@types" ],
        "emitDecoratorMetadata": true,
        "allowSyntheticDefaultImports": true,
        "experimentalDecorators": true,
        "esModuleInterop": true,
        "noUnusedParameters": true,
        "noUnusedLocals": true,
        "noImplicitReturns": true,
        "skipLibCheck": true,
        "strict": true,
    },
}
// jest.config.js
const sveltePreprocess = require('svelte-preprocess');

module.exports = {
    roots: [ '<rootDir>' ],
    transform: {
        '^.+\\.mjs?$': 'babel-jest',
        '^.+\\.tsx?$': 'ts-jest',
        '^.+\\.svelte$': [ 'jest-transform-svelte', {
            typescript: {},
            stylus: {
                includePaths: [ 'src' ],
            },
            postcss: {
                plugins: [ require('autoprefixer') ],
            },
        } ],
    },
    testRegex: '((\\.|/)(feature|test|spec))\\.tsx?$',
    moduleFileExtensions: [ 'ts', 'tsx', 'js', 'mjs', 'json' ],
    moduleNameMapper: {
        '^src/(.*)': '<rootDir>/src/$1',
    },
    moduleDirectories: [ 'node_modules', 'src/node_modules' ],
    transformIgnorePatterns: [
        '/node_modules/(?!@sapper)'
    ],
    testEnvironment: 'node',
};

I'm using Node 14.4, but have not tested it on LTS.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Rich-Harris picture Rich-Harris  路  3Comments

SARFEX picture SARFEX  路  3Comments

freedmand picture freedmand  路  4Comments

mylastore picture mylastore  路  3Comments

milosdjakovic picture milosdjakovic  路  3Comments