Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot find module with typescript and utility module #609

Closed
kbrah opened this issue Jul 28, 2020 · 4 comments
Closed

Cannot find module with typescript and utility module #609

kbrah opened this issue Jul 28, 2020 · 4 comments

Comments

@kbrah
Copy link

kbrah commented Jul 28, 2020

I have root project, one app and one utility module. When I import a component from the utility module in app module it works fine, but for some reason tsserver says cannot find module or its corresponding type declarations. All of the mentioned projects are using Typescript. Any idea how to fix this?

My root project webpack.config.js

// eslint-disable-next-line
const path = require("path");
// eslint-disable-next-line
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
// eslint-disable-next-line
const HtmlWebpackPlugin = require("html-webpack-plugin");
// eslint-disable-next-line
const CopyWebpackPlugin = require("copy-webpack-plugin");

// eslint-disable-next-line
module.exports = {
    // eslint-disable-next-line
    entry: path.resolve(__dirname, "src/root-config"),
    mode: "development",
    devtool: "source-map",
    output: {
        // eslint-disable-next-line
        path: path.join(__dirname, "/dist"),
        filename: "project-root-config.js",
        libraryTarget: "system",
    },
    resolve: {
        extensions: [".ts", ".tsx", ".js"],
        modules: [path.resolve(__dirname, "node_modules")],
    },
    module: {
        rules: [
            { parser: { system: false } },
            {
                test: /\.(ts|tsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader",
                },
            },
            {
                enforce: "pre",
                test: /\.js$/,
                loader: "source-map-loader",
            },
            {
                test: /\.css$/i,
                use: ["style-loader", "css-loader"],
            },
        ],
    },
    devServer: {
        port: 3000,
        historyApiFallback: true,
        headers: {
            "Access-Control-Allow-Origin": "*",
        },
        disableHostCheck: true,
    },
    plugins: [
        new HtmlWebpackPlugin({
            inject: false,
            template: "src/index.ejs",
            templateParameters: {
                // eslint-disable-next-line
                isLocal: true, //env && env.isLocal === "true",
            },
        }),
        new CleanWebpackPlugin(),
        new CopyWebpackPlugin({
            patterns: [{ from: "src/static" }],
        }),
    ],
    externals: [/^@fimlab-ui\/.+$/], // /^@fimlab-ui\/.+$/
};

My utility and module webpack.config.js are default config from webpack-config-single-spa-react-ts

root tsconfig

{
    "compilerOptions": {
        "outDir": "./dist",
        "sourceMap": true,
        "moduleResolution": "node",
        "allowJs": true,
        "noImplicitAny": true,
        "module": "commonjs",
        "target": "es6",
        "jsx": "preserve",
        "esModuleInterop": true,
        "declaration": true,
        "baseUrl": "./src",
        "rootDir": "src"
    },
    "include": ["src/**/*"]
}

app tsconfig

{
    "compilerOptions": {
        "target": "es5",
        "lib": ["dom", "dom.iterable", "esnext"],
        "allowJs": true,
        "sourceMap": true,
        "skipLibCheck": true,
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "noEmit": true,
        "baseUrl": ".",
        "jsx": "react"
    },
    "include": ["src"]
}

utility tsconfig

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "sourceMap": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react"
  },
  "include": ["src/**/*"]
}

my root index.ejs

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Project</title>

  <meta name="importmap-type" content="systemjs-importmap" />
  <script type="systemjs-importmap" src="/importmap.json"></script>
  <script type="text/javascript" src="/jquery-3.1.1.min.js"></script>
  <% if (isLocal) { %>
  <script type="systemjs-importmap">
    {
      "imports": {
        "@project/root-config": "http://localhost:3000/project-root-config.js",
        "@project/app": "http://localhost:3001/app.js",
        "@project/utility": "http://localhost:8081/utility.js"
      }
    }
  </script>
  <% } %>
  <script src="http://localhost:3000/import-map-overrides.js"></script>
  <script src="http://localhost:3000/system.min.js"></script>
  <script src="http://localhost:3000/amd.min.js"></script>
  <script src="http://localhost:3000/named-exports.min.js"></script>
  <template id="single-spa-layout" style="display: none;">
      <single-spa-router>
          <div class="top-nav" style="position: absolute; width: 100%;">
              <application name="@project/app"></application>
          </div>
      </single-spa-router>
  </template>
</head>
<body>
  <script>
    System.import('@fimlab-ui/root-config');
    System.import('@fimlab-ui/app');
  </script>
  <import-map-overrides-full show-when-local-storage="devtools" dev-libs></import-map-overrides-full>
</body>
</html>
@joeldenning
Copy link
Member

Hi @kbrah, good question.

The problem

With single-spa microfrontends, each microfrontend is an in-browser module, but not necessarily a build-time module. Typescript does everything at build-time (not in-browser), so it doesn't know where to find your utility module.

Two options for solutions

  1. Publish your utility module to an npm registry, including its types. Then install it into each other microfrontend's node_modules. Since it's a webpack external, the version in node_modules will only be used for typescript compilation but not for execution in the browser.
  2. Mock the utility module's types, as described here

Other resources

I'm closing this since I believe to have answered the question, but feel free to comment further or reopen.

@sgoutamdefraudit
Copy link

Hi @kbrah, good question.

The problem

With single-spa microfrontends, each microfrontend is an in-browser module, but not necessarily a build-time module. Typescript does everything at build-time (not in-browser), so it doesn't know where to find your utility module.

Two options for solutions

  1. Publish your utility module to an npm registry, including its types. Then install it into each other microfrontend's node_modules. Since it's a webpack external, the version in node_modules will only be used for typescript compilation but not for execution in the browser.
  2. Mock the utility module's types, as described here

Other resources

I'm closing this since I believe to have answered the question, but feel free to comment further or reopen.
I applied the 2nd approach but when I build the app it is throwing "Error: Module not found: Error: Can't resolve '@fundamentals/store' "

@LeonardoRick
Copy link

Hi @joeldenning, I cannot make the error disapear creating a declare module. Can you give more details on how to implement it? I'm not planning to publish this on npm. Thanks.

@shoaib9121
Copy link

@LeonardoRick You can create a file anywhere, ideally under src/ e.g. filename.d.ts

and inside put a declare statement as below:

declare module 'module-name'

Note: All imports from a shorthand module will have the any type.

For further help. Visit this link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants