javascriptreactjstypescriptwebpackbabeljs

'Cannot find module' when using dynamic import


I've deleted CRA and configured webpack/babel on my own. Now I have problems with dynamic imports.

error

This works fine:

import("./" + "CloudIcon" + ".svg")
  .then(file => {
  console.log(file);
})

This doesn't work:

const name = 'CloudIcon';

import("./" + name + ".svg")
  .then(file => {
  console.log(file);
})

I've tried to export files with different types. It didn't work. Have tried to use Webpack Magic Comments, but didn't help either.

I suppose, that something is wrong with my webpack/babel settings, but what?

babel.config.js:

const plugins = [
  "@babel/syntax-dynamic-import",
  ["@babel/plugin-transform-runtime"],
  "@babel/transform-async-to-generator",
  "@babel/plugin-proposal-class-properties"
];


if (process.env.NODE_ENV === 'development') {
  plugins.push('react-refresh/babel'); 
}

module.exports = {
  presets: [[
    "@babel/preset-env", {
      "debug": false,
      "modules": false,
      "useBuiltIns": false
    }],
    ['@babel/preset-react', {throwIfNamespace: false}],
    '@babel/preset-typescript'
  ],
  plugins,
};

webpack.config.js:

require('dotenv').config();
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const webpack = require('webpack');

const reactAppVars = (() => {
  const obj = {};
  for (let key in process.env) {
    if (key.startsWith('REACT_APP_')) obj[key] = process.env[key];
  }
  return obj;
})();

const target = process.env['NODE_ENV'] === 'production' ? 'browserslist' : 'web';

const plugins = [
  new webpack.EnvironmentPlugin({'NODE_ENV': process.env['NODE_ENV'], 'PUBLIC_URL': '', ...reactAppVars}),
  new HtmlWebpackPlugin({template: path.resolve(__dirname, '../public/index.html')}),
  new MiniCssExtractPlugin({filename: '[name].[contenthash].css'}),
  new webpack.ProvidePlugin({process: 'process/browser'}),
  new webpack.ProvidePlugin({"React": "react"}),
];

if (process.env['SERVE']) plugins.push(new ReactRefreshWebpackPlugin());

const proxy = {
//Proxy settings
}

module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "main.js",
    path: path.resolve(__dirname, "../build"),
    assetModuleFilename: '[path][name].[ext]'
  },
  plugins,
  devtool: 'source-map',
  devServer: {
    static: {
      directory: path.resolve(__dirname, "../public"),
    },
    proxy,
    port: 9999,
    hot: true,
  },

  module: {
    rules: [
      { test: /\.(html)$/, use: ['html-loader'] },
      {
        test: /\.(s[ac]|c)ss$/i,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.less$/i,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          {
            loader: 'less-loader',
            options: {
              lessOptions: {
                javascriptEnabled: true
              }
            }
          }
        ]
      },
      {
        test: /\.(png|jpe?g|gif|webp|ico)$/i,
        type: process.env['NODE_ENV'] === 'production' ? 'asset' : 'asset/resource'
      },
      {
        test: /\.svg$/i,
        issuer: /\.[jt]sx?$/,
        use: ['@svgr/webpack', {
          loader: 'file-loader',
          options: {
            name: '[path][name].[ext]'
          }
        }],
      },
      {
        test: /\.(woff2?|eot|ttf|otf)$/i,
        type: process.env['NODE_ENV'] === 'production' ? 'asset' : 'asset/resource'
      },
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            cacheDirectory: true,
          }
        }
      },
      {
        test: /\.([cm]?ts|tsx)$/,
        use: {
          loader: "babel-loader",
          options: {
            presets: [
              "@babel/preset-env",
              "@babel/preset-react",
              "@babel/preset-typescript",
            ]
          }
        }
      },
      {
        test: /\.md$/,
        loader: "raw-loader"
      },
    ],
  },
  resolve: {
    'roots': [path.resolve('./src')],
    'extensions': ['', '.js', '.jsx', '.ts', '.tsx'],
    extensionAlias: {
      ".js": [".js", ".ts"],
      ".cjs": [".cjs", ".cts"],
      ".mjs": [".mjs", ".mts"]
    },
    fallback: {
      'process/browser': require.resolve('process/browser')
    }
  },
  mode: process.env['NODE_ENV'],
  target
}

Solution

  • The problem was the extensions array in webpack

    'extensions': ['', '.js', '.jsx', '.ts', '.tsx']
    

    I changed it to this

    'extensions': ['.js', '.jsx', '.ts', '.tsx', '...']
    

    And now everything works fine.