Dynamic imports on runtime are ignored by Rollup #2463
Comments
|
I use the same And I can confirm, that after rollup v0.66.6, node v10.6.0, npm v6.1.0, Windows 7. |
|
To answer the initial question: This is indeed a harder problem. We might add special code for very specific ways of writing this. Nevertheless it will break down once your arrays contains non-trivial code that can only be evaluated at runtime. |
|
So far as possible I believe quite strongly we should trace and handle these builds, while retaining the hooks for custom behaviours. |
|
My case is to dynamic import a module in a specific folder: Here is my files structure: In file function getTranslation (lang) {
return import(`./locales/${lang}`)
}Is there any possible solutions for rollup to handle this kind of situation? By the way, Webpack solve this problem by wrap every file inside |
|
I think this could work, because you remove the string interpolation. function getTranslation (lang) {
if (lang === 'en') {
return import('./locales/en.js');
}
if (lang === 'zh') {
return import('./locales/zh.js');
}
} |
|
@pieterbeulque is right, unfortunately Rollup dynamic imports do not support string interpolation (yet?). |
|
The problem with string interpolation is that rollup needs to make some assumptions about the host system it runs on (i.e. it is not run in the browser) as well as inject a custom resolver runtime to handle the dynamic import. The custom resolver then needs to properly translate relative paths into absolute paths which leads to either paths from your host system sneaking into the bundle or at the very least needlessly complicated code. (Simple example: You write If you want to directly take the contents of a directory as a base for dynamic imports, I would suggest a better solution that solely has the caveat of not providing the same level of syntactic sugar. The following config will create a virtual module // rollup.config.js
import path from 'path';
import fs from 'fs';
export default {
input: 'src/main.js',
plugins: [{
// this is necessary to tell rollup that it should not try to resolve "dynamic-targets"
// via other means
resolveId(id) {
if (id === 'dynamic-targets') {
return id;
}
return null;
},
// create a module that exports an object containing file names as keys and
// functions that import those files as values
load(id) {
if (id === 'dynamic-targets') {
const targetDir = path.join(__dirname, 'dynamic');
const files = fs.readdirSync(targetDir);
const objectEntries = files
.map(file => ` '${file}': () => import('${path.join(targetDir, file)}')`);
return `export default {\n${objectEntries.join(',\n')}\n};`;
}
return null;
}
}],
output: {
dir: 'dist',
format: 'cjs'
}
}You can now use this virtual module in your code like this: import dynamicTargets from 'dynamic-targets';
// my example files are "test0.js", ..., "test9.js"
const fileName = `test${Math.floor(Math.random() * 10)}.js`;
// import and run the file, then log a message
dynamicTargets[fileName]().then(() => console.log(`imported ${fileName}`));If you feel inspired, it should not be too difficult to generalize this idea into a "real" plugin for everyone to use. |
|
@lukastaegert // for router
const route = {
"path":"data/dispaly/{id}",
"js":"pages/data_dispaly.js",
}
import renderer from route.js;
new renderer();// display pagenow each renderer page may have its own imports and such. Can anyone please propose a solution ? |
|
I interpret the problem as follows:
Vague suggestion:
|
|
@lukastaegert yes . You understood the issue correctly. My App brings router info from server so i cant hardcode imports for my routes But those js files do exit in src/pages folder and they will be fetched on demand when for example a user clicks a button, based on its route information, relevant js will be rendered. |
|
@lukastaegert now see proposal here https://github.com/tc39/proposal-dynamic-import#example |
|
Rollup will create shared chunks automatically if all entry points are part of the same build. These can be either manual, static entry points by adding them to the input option or dynamic ones via dynamic imports. The latter only creates separate chunks if they can be statically resolved. If you create a virtual module as outlined above, this would work out of the box. If they just do not exist at build time, creating shared chunk needs more manual work. |
|
Hey folks. This is a saved-form message, but rest assured we mean every word. The Rollup team is attempting to clean up the Issues backlog in the hopes that the active and still-needed, still-relevant issues bubble up to the surface. With that, we're closing issues that have been open for an eon or two, and have gone stale like pirate hard-tack without activity. We really appreciate the folks have taken the time to open and comment on this issue. Please don't confuse this closure with us not caring or dismissing your issue, feature request, discussion, or report. The issue will still be here, just in a closed state. If the issue pertains to a bug, please re-test for the bug on the latest version of Rollup and if present, please tag @shellscape and request a re-open, and we'll be happy to oblige. |
|
@shellscape This is still an issue in rollup v2.28.2. How do I do something like this: const template = await import(
/* webpackChunkName: "examples-source" */
`../examples/${file}.js`
) |
|
There is now a plugin for that: https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars |
|
It has no support for IIFE bundles, webpack creates different bundles for the files. |
|
Rollup as a while has no support for code-splitting IIFE bundles. You need a runtime loader like AMD or SystemJS for that. Webpack always bundles their proprietary bundler code, which is likely what you mean. With ESM, CommonJS, SytemsJS or AMD output, this plugin should work as expected. |
|
@lukastaegert So is there no way that I can do: Which generates files: With rollup? |
|
Well. not with IIFE format. As I said, use AMD or SystemJS. If you want the ease-of-use of not having to worry about the loader, I can actually recommend using https://github.com/surma/rollup-plugin-off-main-thread . While this plugin appears to be about workers, one effect is that it takes care of embedding a minimal AMD loader into your entry chunks so you get roughly the same experience as when using Webpack. |
|
Thanks, just FYI, I am using rollup for svelte. |
|
Hmm, I've tried to use const module = await import(`../../benchmark/suites/${name}.js`)It always output this line: And the file path is correct. |
|
Oh is it because browser can't read file? Then this plugin only work for Node. |
How Do We Reproduce?
REPL
Expected Behavior
To have
foo.jsbe considered by Rollup as part of the application and copied over topublic/js.Actual Behavior
foo.jsis not copied over or considered for code splitting.I'm not sure if this is hard to do or possible at all.
The text was updated successfully, but these errors were encountered: