Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I import custom ES6 modules?

I have one JavaScript file at http://localhost:8000/static/home/js/edit_sites.js, which is trying to access a module at localhost:8000/static/global/js/modules/reorder.mjs.

edit_sites.js

import { reorder } from '/static/global/js/modules/reorder.mjs';

$(() => {
  reorder($('.screenshot-list'));
});

reorder.mjs

export const reorder = ($ul) => {
  // reorder screenshots by clicking arrows
  const $up = $ul.find('.controls :first-child');
  const $down = $ul.find('.controls :last-child');
  const paddingBottom = 8;

  $up.on('click', function () {
    const $li = $(this).parents('li');

    if (!$li.is(':first-child')) {
      const $prev = $li.prev();

      $li.animate(
        { bottom: `${$prev.outerHeight() + paddingBottom}px` },
        500,
        function () {
          $(this).after($prev.detach()).prop('style', '');
        },
      );

      $prev.animate(
        { top: `${$li.outerHeight() + paddingBottom}px` },
        500,
        function () {
          $(this).prop('style', '');
        },
      );
    }
  });

  $down.on('click', () => {
    const $li = $(this).parents('li');

    if (!$li.is(':last-child')) {
      const $next = $li.next();

      $li.animate(
        { top: `${$next.outerHeight() + paddingBottom}px` },
        500,
        function () {
          $(this).before($next.detach()).prop('style', '');
        },
      );

      $next.animate(
        { bottom: `${$li.outerHeight() + paddingBottom}px` },
        500,
        function () {
          $(this).prop('style', '');
        },
      );
    }
  });

  // update value of hidden order field on submit
  $('form').on('submit', function () {
    let order = '[';

    $ul.children('li').each(function () {
      order += `${$(this).data('id')}`;

      if (!$(this).is(':last-child')) {
        order += ', ';
      }
    });

    order += ']';

    $('input[name="order"]').val(order);

    return true;
  });
};

However, when I try to minify it using Closure, I get this error message:

java -jar bin/closure-compiler-v20200504.jar --language_in=STABLE --js home/static/home/js/edit_sites.js --js_output_file home/static/home/js/edit_sites.min.js
home/static/home/js/edit_sites.js:1: ERROR - [JSC_JS_MODULE_LOAD_WARNING] Failed to load module "/static/global/js/modules/reorder.mjs"
import { reorder } from '/static/global/js/modules/reorder.mjs';
^

1 error(s), 0 warning(s)

I wonder how I should define the path, as several attempts to do so did not work. Some paths (of many) I've tried:

import { reorder } from './home/static/global/js/modules/reorder.mjs';
import { reorder } from './static/global/js/modules/reorder.mjs';
import { reorder } from '/home/matt/Repositories/project-dir/home/static/global/js/modules/reorder.mjs';

I think part of the problem is that Closure is trying to access the module from a different location than the script is. I'm new to writing modules, so I'm not entirely sure where the . directory even is. Closure executes in /home/matt/Repositories/project-dir, but when I stem my path from there, I get an error. Here's my static directory structure with irrelevant files omitted, in case you'd like to step through visually:

arch-laptop static > tree (pwd)
/home/matt/Repositories/project-dir/home/static
├── global
│   ├── img
│   ├── js
│   │   └── modules
│   │       └── reorder.mjs
│   └── sass
├── home
│   ├── css
│   ├── img
│   ├── js
│   │   └── edit_sites.js
│   └── sass
└── lib
    ├── css
    └── js

13 directories, 55 files

Edit

I should have made it clear in my original post that my ultimate goals are:

  1. Minifying these two files, and
  2. Using them without error.

Despite receiving useful information here, I am still stuck on step one. I have been able to minify the ES6 module, reorder.mjsreorder.min.mjs, but not the regular ES6 file, edit_sites.js.

I found a Closure compile option that might be useful:

java -jar ./bin/closure-compiler-v20201102.jar --help | less -R
…
JS Modules:
 --js_module_root VAL                   : Path prefixes to be removed from ES6
                                          & CommonJS modules.
…

…so I update line 1 of edit_sites.js to include the path to the newly created reorder.min.mjs file, relative to edit_sites.js (as the two answers below suggested):

import { reorder } from '../../global/mjs/modules/reorder.min.mjs';

…but when I try compiling, I get the same error as before:

java -jar bin/closure-compiler-v20201102.jar --js_module_root ../../global/mjs/modules --js home/static/home/js/edit_sites.js --js_output_file home/static/home/js/edit_sites.min.js
home/static/home/js/edit_sites.js:2:0: ERROR - [JSC_JS_MODULE_LOAD_WARNING] Failed to load module "../../global/mjs/modules/reorder.min.mjs"
  2| import { reorder } from '../../global/mjs/modules/reorder.min.mjs';
     ^

1 error(s), 0 warning(s)

I've wondered if:

  1. I should be using an import statement in a regular JS file at all. For example, I've tried removing the import from edit_sites.js, minifying it without error, and importing with the following HTML:
<script type="module" src="/static/global/mjs/reorder.min.mjs"></script>
<script src="/static/home/js/edit_sites.min.js"></script>

        However, I get this error in the console:

11:23:23.859 Uncaught ReferenceError: assignment to undeclared variable reorder
    <anonymous> http://localhost:8000/static/global/mjs/reorder.min.mjs:8
reorder.min.mjs:8:69
  1. I should be using a path relative to closure-compiler-v20200504.jar with the --js_module_root flag. However, changing line 1 to
import { reorder } from '../home/static/global/mjs/modules/reorder.min.mjs';

        doesn't work, either.

like image 386
Matt McCarthy Avatar asked Nov 12 '20 14:11

Matt McCarthy


People also ask

How do I import ES6 into browser?

Safari, Chrome, Firefox and Edge all support the ES6 Modules import syntax. Here's what they look like. Simply add type="module" to your script tags and the browser will load them as ES Modules. The browser will follow all import paths, downloading and executing each module only once.

How do I import and export ES6?

With the help of ES6, we can create modules in JavaScript. In a module, there can be classes, functions, variables, and objects as well. To make all these available in another file, we can use export and import. The export and import are the keywords used for exporting and importing one or more members in a module.

Can you import modules in JavaScript?

You can import modules into a file in two ways, based on if they are named exports or default exports. Named exports are constructed using curly braces. Default exports are not.

Does ES6 support import?

ES6 modules are automatically strict-mode code, even if you don't write "use strict"; in them. You can use import and export in modules.


2 Answers

I would use '../' to step back a few folders and then '/:name' to step forward.

Try: Import { reorder } from '../../global/js/modules/reorder.mjs';

Also if your text editor has intellisense it should suggest folders to you after you type '/'. I recommend using vscode or sublime for a project like this.

like image 135
Austin Karren Avatar answered Oct 07 '22 06:10

Austin Karren


The closure are looking for the module file, so the path is incorrect;

try to put ../../static/global/js/modules/reoder.mjs or even ../../global/js/modules/reoder.mjs one of those can handle this :)

like image 1
PabloWeb18 Avatar answered Oct 07 '22 07:10

PabloWeb18