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

Discrepancy with es modules / duplicated multiple entries #3575

Closed
dy opened this issue Sep 27, 2019 · 8 comments
Closed

Discrepancy with es modules / duplicated multiple entries #3575

dy opened this issue Sep 27, 2019 · 8 comments
Labels

Comments

@dy
Copy link

dy commented Sep 27, 2019

🐛 bug report

Take index.html:

<script src="./x.js"></script>
<script src="./x.js"></script>
// x.js
import './y.js'
// y.js
console.log('foo')

If we build it with parcel parcel serve --no-hmr index.html, it includes/runs y.js two times.

Same time, if we use native ES modules:

<script>
var parcelRequire // hello #3545 
</script>
<script type="module" src="./x.js"></script>
<script type="module" src="./x.js"></script>

The y.js is run once.

🤔 Expected Behavior

y.js should be run once.

😯 Current Behavior

Runs y.js multiple times.

💁 Possible Solution

Same as browserify - it handles that fine.
Should be code-splitting engaged or something, to avoid dupes in output.
I wouldn't bundle per-entry, instead I'd split out shared imports and reuse them.

🔦 Context

spect enables aspect-oriented approach to web-sites, so that for example material-design components are initialized separately from main application logic, and separate from "decorative" logic (and separately from i18n, dataschema etc).

💻 Code Sample

For example, that spect app logic can be loaded each by own entry:

<script src="./materialize.js"></script>
<script src="./app.js"></script>
<script src="./decorations.js"></script>
<script src="./i18n.js"></script>
<script src="./microdata.js"></script>

Since each that entry includes spect internally:

// materialize.js
import { use } from 'spect'
import { MDLFab } from '@material/fab'

use('.mdl-fab', el => el.mdlComponent = new MDLFab(el))
// app.js
import { on } from 'spect'

on('.app-form', 'submit', e => {
   // ...send form
})
....

That results in duplication of spect imports N times - per each entry.

🌍 Your Environment

Software Version(s)
Parcel 1.12.3
Node -
npm/Yarn
Operating System
@mischnic
Copy link
Member

<script src="./x.js"></script>
<script src="./x.js"></script>

Personally, I would except everything to run twice here.

The CommonJS environment that Parcel emulates (and that ES6 imports are essentially transpiled to - doing require("foo") twice also executes that module only once) is only valid within that bundle.

@dy
Copy link
Author

dy commented Sep 28, 2019

@mischnic
For commonjs environment all bundlers provide code-splitting:
browserify, rollup, webpack. They have no problems sharing duplicate modules.
Also that's not the case of native ES modules. Also that creates code duplication and problems of global cache / singletons.

What's the use of having isolated bundles? Does it solve any problem?

@devongovett
Copy link
Member

Why are you importing the same script twice?

This is hard to do without wrapping every module in a function. When tree shaking/scope hoisting, this is exactly what we are trying to avoid.

I don't think this is possible.

@felipemullen
Copy link

I don't think this was justly closed. The code sample illustrated in the description does not include repetitions of the same script, but modules are claimed to have been duplicated in each.

That is the behavior I am seeing as well. I have a singleton being imported in a few files

import { MyClass } from '../module'

And every file that uses the singleton ends up having its own separate copy of the module included in the output file. This does not appear to be standard behavior

@mischnic
Copy link
Member

@felipemullen Could you please open a new issue with a reproduction?

@felipemullen
Copy link

@mischnic I've created a demonstration here: https://github.com/felipemullen/parcel-dupes

In the console output, you can see that modules A and B are included in the output for both run.js and run2.js which is not expected, and I think satisfies this original issue.

I wasn't sure if I should create a new issue yet because I feel like this behavior wouldn't have been overlooked. I must be doing something wrong?

Anyway, I can create a new issue if you think it is more appropriate

@mischnic
Copy link
Member

mischnic commented Dec 2, 2019

@felipemullen Module hoisting with multiple scripts

    <script src="run.js"></script>
    <script src="run2.js"></script>

isn't supported by Parcel, mainly because few people have requested that and putting import "run.js"; import "run2.js"; in an index.js file works as expected in this case. (unless you have some reasons against this?)
Without es modules, we would even have to pollute the global namespace to access the modules in the first script (so C and D in your case).

@felipemullen
Copy link

Ah, I see. That's a pity. For context, I'll explain the scenario, maybe it will help others who come across this situation:

I am working on an enterprise level angular 1.6 project, and I have been slowly modernizing it where I can (The goal is to move away from angular in the long run)

The issue came up because multiple angular services (in separate files) make use of functionality that was extracted into a module, resulting in the complete duplication of the module in each service.

I understand now, thank you for the clarification. I will find a way around it 🐒

Parcel is a great project, many thanks to everyone behind it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants