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

Can't get individual ES6 module loading to work as per wiki page #381

Closed
lpar opened this issue Jun 10, 2020 · 23 comments
Closed

Can't get individual ES6 module loading to work as per wiki page #381

lpar opened this issue Jun 10, 2020 · 23 comments
Assignees
Labels
enhancement potential improvement help wanted need your suggestion

Comments

@lpar
Copy link

lpar commented Jun 10, 2020

According to the wiki, you can import only the individual modules you want using ES6 imports. e.g.

import Button from 'bootstrap.native/src/components/button-native.js'

let myBtnInit = new Button('#myBtnID');

However, button-native.js depends on shorter-js:

import { hasClass } from 'shorter-js/src/class/hasClass.js';
import { addClass } from 'shorter-js/src/class/addClass.js';
...

I can't work out how to get those import paths to work, even for a local deployment, so the browser just gives me TypeError: Error resolving module specifier: shorter-js/src/class/hasClass.js.

Similarly, I can import the whole thing from the CDN via:

import BSN from "//cdn.jsdelivr.net/npm/[email protected]/dist/bootstrap-native.esm.min.js";

But the corresponding single-module import doesn't work:

import Button from "//cdn.jsdelivr.net/npm/[email protected]/src/components/button-native.js";

Same problem -- can't resolve the shorter-js dependency.

Is there a build or deploy process I need to go through first to get individual ES6 components to work?

@thednp
Copy link
Owner

thednp commented Jun 11, 2020

I don't know how to work out this dependency yet. The point is to create custom builds and everything is working fine, so perhaps you want to work your way with custom builds?

Either way, perhaps making sure you have it's dependencies installed and importing into your ES6 file?

I'm also open to any suggestions.

@thednp
Copy link
Owner

thednp commented Jun 11, 2020

Also thanks for the wiki edit, you probably tested it, I wrote a quick wiki update to rush the release..

@lpar
Copy link
Author

lpar commented Jun 11, 2020

The problem with the code that's there right now is that browsers don't support bare import specifiers like 'shorter-js/src/class/hasClass.js', they need to be relativized with ./ or absolute paths.

If I assume shorter-js will be at the same level as bootstrap.native I can fix up the import paths to be relative, for example in modal-native.js:

import { hasClass } from '../../../shorter-js/src/class/hasClass.js';
import { addClass } from '../../../shorter-js/src/class/addClass.js';
import { removeClass } from '../../../shorter-js/src/class/removeClass.js';

After relativizing all the import paths in the current sources like that, I can then do:

  import Modal from './bootstrap.native/src/components/modal-native.js';
  const modal = new Modal("#modal");
  modal.show();

...and it works. So I can think of a few options:

  1. Use relative paths throughout, and fix the non-ES6 build process to work with that.
  2. Have a build process which converts the import paths in modules to either relative or absolute, as specified by the user, based on how they're planning to deploy.
  3. Have a bundled up shorter-js build with all the functions needed by all the bootstrap.native modules in a single file.

I'd probably take the last approach. It looks as if

rollup src/index.js --format es --name 'shorter-js' --file shorter-js.es.js

will build an all-in-one ES6 module version of shorter-js, so you could have a step to do that and dump it into the bootstrap.native/src directory ready for deployment, and then have the imports in the module sources use (say) ../shorter-js.es.js for the import path.

@thednp
Copy link
Owner

thednp commented Jun 11, 2020

What if I produce a module for each component, similar cu what Bootstrap does?

Your dist/components folder would hold these, and you can call them anywhere anyway you want.

@lpar
Copy link
Author

lpar commented Jun 11, 2020

Including shorter-js in dist as part of the build? That would work.

Or I guess you could rollup the necessary shorter-js code into each component, at the cost of some additional overhead.

@thednp
Copy link
Owner

thednp commented Jun 11, 2020

You think we should remove shorter-js? Suddenly the event handling is gonna get wacky, especially for stuff like Carousel.

@lpar
Copy link
Author

lpar commented Jun 11, 2020

Could be worth looking into. For example, native hasClass and addClass are barely any longer than the shorter-js versions these days.

@thednp
Copy link
Owner

thednp commented Jun 12, 2020

I agree about classes.

Are you deploying something like a bundle by any chance? I'm thinking maybe installing the dependency and importing it along would help solve the problem?

@thednp
Copy link
Owner

thednp commented Jun 12, 2020

I am considering a future plan to rework this stuff, removing dependency on class and event delegation, but there are some little things that keep repeating over and over.

On the issue at hand, do you have a definite plan to solve this issue without creating custom builds?

@lpar
Copy link
Author

lpar commented Jun 12, 2020

Right now my application is in early development. I don't have a bundler — it's a Go application with minimal front-end vanilla JavaScript — but the build process preminifies and precompresses everything. My plan so far is to just import the whole of bootstrap-native.esm.min.js, as it's only 9879 bytes after brotli and will be cached in the browser. That's less than half the size of either jQuery or the regular Bootstrap JavaScript bundle, so still a massive win.

I really opened the ticket to alert you that the individual module loading doesn't work at present, and maybe help fix that if there's a way to do it without breaking the existing build process.

@thednp
Copy link
Owner

thednp commented Jun 12, 2020

You're very safe to work with custom builds, it's so easy, you just don't care.

@lpar
Copy link
Author

lpar commented Jun 12, 2020

Not sure what you are getting at there?

Anyway, looks like the easiest option is to build standalone ES6 modules by rolling in shorter-js, e.g.

rollup components/modal-native.js --file components/modal-native.esm.js

Those can then be loaded as modules. So maybe that's what the wiki page should suggest.

@thednp
Copy link
Owner

thednp commented Jun 12, 2020

Even better, you can do

trunk> $
npm run custom INPUTFILE:src/components/button.js,OUTPUTFILE:dist/button.esm.js,MIN:false,FORMAT:esm

I think browsers should be able to handle this dependency handling in the future.

@lpar
Copy link
Author

lpar commented Jun 12, 2020

Perfect! Updated the wiki page.

@thednp
Copy link
Owner

thednp commented Jun 12, 2020

Thank you :)

thednp added a commit that referenced this issue Jun 18, 2020
* changed all util and imports structure for more accurate bundles
* addressing #381, added more build scripts, now `dist/components/` folder holds UMD and ESM modules for all components, @lpar can have a look?
* removed dependency on `shorter-js` for events handling, class manipulation, and more, see commit file changes
@thednp
Copy link
Owner

thednp commented Jun 18, 2020

@lpar please check latest master, I've update the wiki accordingly, please confirm we're all right :)

@lpar
Copy link
Author

lpar commented Jun 18, 2020

Checked and the distributed ESM build of modal-native in dist/components works, that's the one I need so far. I assume if that works the others will.

@thednp
Copy link
Owner

thednp commented Jun 19, 2020

@lpar I'm making a custom build tool rollup-module.js for modules and I need to know some stuff as well as your opinion on UMD/CJS.

  • Are the IIFE, UMD and CJS files the same thing basically?
  • When using
var Button = require "dist/components/button-native.js"

you basically expect it to work with

var btn = new Button('selector')

and not

var btn = new BSN.Button('selector')

correct?

@thednp
Copy link
Owner

thednp commented Jun 19, 2020

@lpar I've updated the code, if you check my last commit you will understand.

Basically now you can do new Button(target) after require.

@thednp thednp added enhancement potential improvement help wanted need your suggestion labels Jun 19, 2020
@lpar
Copy link
Author

lpar commented Jun 20, 2020

I'm afraid I've not used UMD or CJS client side. Until ES6 modules were standardized I just used revealing module pattern via IIFE in my client-side code, so that I didn't have to adopt a whole transformation toolchain.

Looks like you've got a bad path in index.js:

> yarn run custom FORMAT:iife
yarn run v1.22.4
$ rollup -c --environment FORMAT:iife

src/index.js → ./dist/bootstrap-native.iirc.js...
[!] Error: Could not resolve './util/removeDataAPI.js' from src/index.js

The file is actually named removeDataApi.js, and Linux is case-sensitive for filenames. After fixing that, yarn run custom FORMAT:iife builds /dist/bootstrap-native.iife.js for me.

Using the IIFE version you'll still end up with a single BSN object and have to refer to new BSN.Button. That can be fixed if building individual components, by using --name for each one, for example:

FORMAT=iife INPUTFILE=src/components/modal-native.js \
OUTPUTFILE=dist/components/modal-native.iife.js rollup -c --name Modal

I can then do:

<script src="modal-native.iife.js"></script>

<script>
  var mdl = new Modal("#modal");
  mdl.show();
</script>

and it works. I assume that would work for UMD format too.

@thednp
Copy link
Owner

thednp commented Jun 20, 2020

I've updated the file name, will release a new version as soon as I can. I think in the end it's up to you to create your own files and own formats, I've put up the tools for you to easily work it out.

@thednp
Copy link
Owner

thednp commented Jun 20, 2020

@lpar I've made a new build script rollup.module.js and here's how it works:

rollup --environment MODULE:tooltip,FORMAT:iife,MIN:false -c rollup.module.js

In addition you can specify a destination via OUTPUTFILE, by default the destination is dist/components

@thednp
Copy link
Owner

thednp commented Jul 3, 2020

@lpar are we good to close this once and for all?

@thednp thednp closed this as completed Jul 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement potential improvement help wanted need your suggestion
Projects
None yet
Development

No branches or pull requests

2 participants