2

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
}

2 Answers 2

4

What is basically happen that when you have defined import path, webpack will include that code in already existing chunk. When you have a dynamic import (which translated to Regex) it will take all files that correspond to this Regex and place them in a different chunk.

It hard to determine from the details if you serve this additional chunks and the browser can reach them. Network and server logs is a good start.

https://webpack.js.org/guides/code-splitting/#prefetchingpreloading-modules

Sign up to request clarification or add additional context in comments.

1 Comment

Dynamic imports don't even work in a new project. I've created CRA project, added my package.json, webpack and babel configs from the previous project.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.