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

RFC: Import glob tokens #125

Open
jamiebuilds opened this issue Dec 8, 2017 · 15 comments
Open

RFC: Import glob tokens #125

jamiebuilds opened this issue Dec 8, 2017 · 15 comments
Labels
💬 RFC Request For Comments Stale Ignore This issue is exempt from getting flagged as stale and autoremoved

Comments

@jamiebuilds
Copy link
Member

jamiebuilds commented Dec 8, 2017

Webpack has the concept of require contexts which are (in my opinion) completely broken.

When you have a require expression like:

require("./template/" + name + ".ejs");

Webpack basically turns that into a regex which in glob form is:

./template/**/*.ejs

Which is both the correct thing for it to do in that scenario and very very bad.

To see how bad this is, try introducing a symlink between two locations that are matched by the glob.


Instead of that, I would like to see something along the lines of:

import { token } from 'parcel-bundler';

const route = token`./routes/*/index.js`;

function loadRoute(name) {
  return import(route(`./routes/${name}/index.js`));
}

This way we can statically extract out the path from the token and match it against the file system in a reasonable way.

We can also validate the import on the client when you call token(glob)(url).

  • Using import { token } from 'parcel-bundler'; avoids adding anything new to the language
  • Using a tagged template expression "token`glob`" means that we can ignore any interpolations so that it has to be static.
  • We can replace the token with regex on the client to avoid creating a massive runtime with a parser and compiler and everything.
@chee
Copy link

chee commented Dec 8, 2017

I'm into this being static.
I like the idea that it is a function that a person can read to understand, and that it would continue to work even if parcel was not being used as the bundler.

I'm confused about the call to token there, where it does not have any interpolations, wouldn't token get called with only ['./routes/*/index.js']?

Could something like this work?:

import {token} from 'parcel-bundler'

function loadRoute (name) {
  return import(token`./routes/${name}/index.js`)
}

or

import {token} from 'parcel-bundler'

const route = token('./routes/*/index.js')

function loadRoute (name) {
  return import(route(name))
}

@chee
Copy link

chee commented Dec 8, 2017

Which is both the correct thing for it to do in that scenario and very very bad.

^ 😃

@devongovett
Copy link
Member

Parcel actually already supports glob imports:

// import an object listing all the routes
import routes from './routes/*/index.js';

// access one
console.log(routes.blog);

Don't think dynamic imports would work the way you might expect here though.

@chee
Copy link

chee commented Dec 8, 2017

I think the hope here is to avoid an unwanted glob import, if I understand correctly.

For someone who wants to import the price of dog, cheese and foxhound from data to be able to do:

const dataSources = ['dog', 'cheese', 'foxhound']
const data = Promise.all(dataSources.map(source => import(`./data/${source}/price.js`)))

And for Parcel to avoid bundling every other file on the system that matches data/*/price.js because it doesn't know that it might need it.

In this case, static analysis would tell you that you only needed to bundle dog/price, cheese/price and foxhound/price and there's no need for any other files to be built.

@chee
Copy link

chee commented Dec 8, 2017

Would there be a fallback to the Webpack strategy (glob + grab everything), if somehow the path was not able to be statically inferred? for instance:

function loadAlarmBells () {
  return import(`./src/${window.library}`)
}

@jamiebuilds
Copy link
Member Author

Would there be a fallback to the Webpack strategy (glob + grab everything), if somehow the path was not able to be statically inferred

No, that's exactly what I want to avoid. You must be explicit about what is included in the import.

Parcel actually already supports glob imports

I'm not sure it should support globs like that. Using dynamic imports where you load one at a time is better for apps and follows the spec

Don't think dynamic imports would work the way you might expect here though.

I'm not sure what you mean. token(glob)(url) would return a string, but it'd be validated by the glob. token(glob) would be the syntax that specifies which dependencies to add

@DeMoorJasper DeMoorJasper added the 💬 RFC Request For Comments label Dec 13, 2017
@chee
Copy link

chee commented Dec 15, 2017

i'm unsure about the intermediary token function now.

if the user does import(`./routes/${myRoute}`) and we can't figure out the possible values of myRoute, what is different with import(token(glob)(`./routes/${myRoute}`))?

@jakoblind
Copy link

I need this feature to be able to use parcel in one larger code base I am working on! Happy to find that you are discussing it 👍

The proposed solution would require importing parcel code into my production code base. I am a bit hesitant to that. I think build configuration and production code should be separated.

For my specific use case I would prefer the way webpack handles this: including "everything". How common is having symlinks in a code base?

@bmmpt
Copy link

bmmpt commented Sep 26, 2019

There seem to be some many developers interested in this functionality import('./routes/${myRoute}') (another one right here!), other issues being closed covering basically this problem and pointing to here, there is another bundler that already achieves this (but we don't want to use it for other reasons), and it's been 9 months with no word on this?
Is this dead? Should I just use the other bundler? 😢 Or should I use a work around with no code splitting, hoping that sometime soon this will be available with parcel?

@mischnic mischnic added the Stale Ignore This issue is exempt from getting flagged as stale and autoremoved label Mar 20, 2021
@parcel-bundler parcel-bundler deleted a comment from github-actions bot Mar 20, 2021
@blessanm86
Copy link

Hit this issue today. I am trying to give parcel a try by migrating our app from Webpack. Our app loads the router during runtime

const Router = React.lazy(() => import(`./routes/${getAppConfig().country}`));

It would be great if this is somehow supported without glob imports.

@ng-hai
Copy link

ng-hai commented Feb 3, 2022

Would love if dynamic import is supported. I'm running into this issue when building a blog with MDX

import { lazy, Suspense } from "react";
import { useParams } from "react-router-dom";

export default function BlogDetail() {
  const { postId } = useParams();
  const Post = lazy(() => import(`~src/blogs/${postId}.mdx`));

  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Post />
    </Suspense>
  );
}

@devongovett
Copy link
Member

See https://parceljs.org/features/dependency-resolution/#glob-specifiers

@ng-hai
Copy link

ng-hai commented Feb 4, 2022

@devongovett I have tried it but still not working, it said cannot find module even though static import is fine.

Might be it is caused by invoking at run-time 🤔

@cangSDARM
Copy link

I think a solution similar to webpack's magic annotation is best, or the token method as mentioned above.

webpack style:

  const search = React.useMemo(() => {
    const module = import(
      /* webpackInclude: /engine\.ts$/ */
      /* webpackMode: "lazy" */
      `@/component/Dictionaries/${dictId}/engine.ts`
    );
    console.log(module);
  }, [dictId]);

token style:

import {token} from 'parcel-bundler'

function loadRoute (name) {
  return import(token`./routes/${name}/index.js`)
}

@tankakatan
Copy link

Are there any updates on this issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💬 RFC Request For Comments Stale Ignore This issue is exempt from getting flagged as stale and autoremoved
Projects
None yet
Development

No branches or pull requests