如何使用 rollupjs 动态导入名称由参数定义的模块?

How to dynamically import a module which name is defined by a param with rollupjs?

src/dynamicImport.js


export default function dynamicImport(path) {
    const parts = path.split('/');
    // 去掉后缀.js
    const namespace = parts.pop().replace(/\.\w+$/, '');
    let mid = '';

    if (parts.length) {
        mid = `${parts.join('/')}/`;
    }

    return new Promise((resolve, reject) => {
        console.log(mid, namespace)
        import(
            `@src/${mid}` + namespace + '.js'
        )
            .then(module => {
                resolve(module);
            })
            .catch(err => {
                reject(err);
            });
    });
}

src/index.js

dynamicImport('lib/test').then(({ default: test}) => {
    test();
})

src/lib/test.js

export default function test() {}

rollup.config.js

const rollup = require('rollup');
const babel = require('rollup-plugin-babel')
const resolve = require('rollup-plugin-node-resolve')
const commonjs = require('rollup-plugin-commonjs')
const alias = require('@rollup/plugin-alias')
const { uglify } = require('rollup-plugin-uglify')
const postcss = require('rollup-plugin-postcss')
const replace = require('@rollup/plugin-replace')
const path = require('path');
const getBabelConfig = require('./getBabelCommonConfig.js');

const dirs = {
    src: path.resolve(__dirname, '../src'),
    dist: path.resolve(__dirname, '../dist'),
}



const getInputOptions = (isDev, isMinify) => {
    const babelConfig = getBabelConfig(false);
    babelConfig.runtimeHelpers = true;
    const inputOptions = {
        input: path.resolve(dirs.src, 'index.js'),
        plugins: [
            replace({
                'process.env.NODE_ENV': isDev ? 'development' : 'production'
            }),
            postcss({
                extensions: ['.css', '.less'],
                extract: true,
                modules: true,
                minimize: isMinify
            }),
            alias({
                resolve: ["",".js"],
                entries: {
                    '@lib': path.resolve(__dirname, '../src/lib'),
                    '@src': path.resolve(__dirname, '../src')
                }
            }),
            resolve({
                extensions: ["",".js"],
            }),
            commonjs({
                include: /node_modules/
            }),
            babel({
                ...babelConfig,
                extensions: [".js"]
            })
        ]
    };

    if (isMinify) {
        inputOptions.plugins.push(uglify());
    }

    return inputOptions;
}

const getOutputOptions = (isMinify) => {
    return {
        format: 'umd',
        file: path.resolve(dirs.dist, isMinify ? 'index.min.js' : 'index.js'),
        name: 'test1',
        sourcemap: true
    }
}

const compile = async () => {
    const inputOptions = getInputOptions(true, false);
    const bundle = await rollup.rollup(inputOptions);
    const outputOptions = getOutputOptions(false);
    await bundle.generate(outputOptions);
    await bundle.write(outputOptions);
}


const build = async () => {
    const inputOptions = getInputOptions(true, true);
    const bundle = await rollup.rollup(inputOptions);
    const outputOptions = getOutputOptions(true);
    await bundle.generate(outputOptions);
    await bundle.write(outputOptions);

}


const watch = () => {
    const watchOptions = {
        ...getInputOptions(true),
        output: [getOutputOptions()],
        watch: {
            exclude: 'node_modules/**'
        }
    };

    const watcher = rollup.watch(watchOptions);

    watcher.on('event', event => {
        // event.code can be one of:
        //   START        — the watcher is (re)starting
        //   BUNDLE_START — building an individual bundle
        //   BUNDLE_END   — finished building a bundle
        //   END          — finished building all bundles
        //   ERROR        — encountered an error while bundling
        //   FATAL        — encountered an unrecoverable error
    });
}

const isDevelopment = ['NODE_DEV', 'BROWSER_DEV'].indexOf(process.env.NODE_ENV) >= 0;

if (isDevelopment) {
    watch(true);
} else {
    compile();
    build();
}

这不是在 dist 中创建的块 js。仅构建 index.js。使用 rollup.js.

构建代码时没有错误

/dist/index.js

(function (factory) {
    typeof define === 'function' && define.amd ? define(factory) :
    factory();
}((function () { 'use strict';

    function dynamicImport(path) {
      var parts = path.split('/'); // 去掉后缀.js

      var namespace = parts.pop().replace(/\.\w+$/, '');
      var mid = '';

      if (parts.length) {
        mid = "".concat(parts.join('/'), "/");
      }

      return new Promise(function (resolve, reject) {
        console.log(mid, namespace);
        import("@src/".concat(mid) + namespace + '.js').then(function (module) {
          resolve(module);
        }).catch(function (err) {
          reject(err);
        });
      });
    }

    dynamicImport('lib/test').then(function (_ref) {
      var test = _ref.default;
      test();
    });

})));
//# sourceMappingURL=index.js.map

============================================

在 webpack 中我可以像这样动态导入模块:

import(
    /* webpackChunkName: "[request]" */
    `@src/${mid}` + namespace
 ).then()

我如何使用汇总来做到这一点。我需要用参数传递模块名称。

不幸的是,我发现 rollup 目前不支持动态导入中的变量。
请查看这些问题:
https://github.com/rollup/rollup/issues/2463
https://github.com/rollup/rollup/issues/2097
它只能用定义的字符串来完成:

function localeDynamicImport (locale) {
  if (lang === 'en') {
    return import('./locales/en.js');
  }

  if (lang === 'zh') {
    return import('./locales/zh.js');
  }
}