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

ES6 dependencies are not compiled #261

Open
sashafirsov opened this issue Feb 6, 2019 · 5 comments

Comments

Projects
None yet
2 participants
@sashafirsov
Copy link

commented Feb 6, 2019

Upon generating the JS based portlet with yo liferay-bundle and adding "@vaadin/vaadin-upload" npm dependency, the browser gives an error 'Uncaught SyntaxError: Unexpected string' on generated code

Liferay.Loader.define('@js-based-portlet$vaadin/vaadin-upload@4.2.1/vaadin-upload', ['module', 'exports', 'require'], function (module, exports, require) {
  var define = undefined;
  import './theme/lumo/vaadin-upload.js';
});

On line 3 the static 'import' definitely is a wrong syntax.

The source of error is in vaadin-upload dependency taken from node_modules. Which instead of been compiled with Babel, had been injected without processing. As you can guess the file comprise just one line

import './theme/lumo/vaadin-upload.js';

The liferay-npm-bundler does not use .babelrc 'env' preset which is used for compiling the sources but not for dependencies.

Unfortunately I was not able to locate any doc which will guide to tune up liferay-npm-bundler with another preset than default, meaning not able to trigger compilation of ES6 module dependencies.

@sashafirsov

This comment has been minimized.

Copy link
Author

commented Feb 7, 2019

Not sure whether it fall into same bucket... The relative path is not resolved not just in node_module dependencies but in source project as well.

@izaera izaera added the question label Feb 7, 2019

@izaera

This comment has been minimized.

Copy link
Member

commented Feb 7, 2019

Hi @sashafirsov. I'm not an expert in Vaadin, so I don't know what is the usual toolchain.

As far as I have investigated, it looks like the package you have problems with is written in ES6, probable because:

  1. It defines webcomponents and assume that your browser will be able to interpret it or,
  2. It needs an specific build process

It is intended that the liferay-npm-bundler does not process node_modules dependencies because there's no way it can know how to build them unless someone tells it how to. Also, liferay-npm-bundler calls babel but only for wrapping the modules inside AMD calls and do other transformation tasks, not for compiling/building third party projects.

To sum up: the bundler expects to receive its input in ES5 CommonJS format. That's true for your project's code as well as for your node dependencies.

Said that, you can configure any babel plugins used by the extender in its .npmbundlerrc file so, in theory you could transpile those modules while the bundler is packing them. The only difficulty that could areise would be telling it which node_modules need processing by Babel and which doesn't.

Another possibility would be doing it before the bundler kicks in: running a build step that compiles those files inside your node_modules and modifies the package.json to point to the compiled versions.

However, I suspect that the real problem may be in what you are trying to do.

  1. Are you sure those Vaadin modules are intended to be loaded from an AMD loader?
  2. What is the usual way to build a Vaadin project when not using the bundler?
  3. How do you use those modules inside an standard webapp project?
@sashafirsov

This comment has been minimized.

Copy link
Author

commented Feb 7, 2019

@izaera, about ES6 module format in NPM. It is a conscious choice of Google Polymer team and many other highly reused frameworks. The reason is that it is

  • platform neutral: runs as is in Node and in all modern browsers. No transpiling needed.
  • could be compiled for targeted platforms( read per-browser ). Polymer build by defaults renders 3 bundles, targeting legacy(IE), moderate( old mobile ones, old Safari) and top-notch browsers( Chrome & FF ). Having precompiled code in NPM makes code use in modern browsers inefficient, those are capable to run without any transpilers with minimal footprint.

So it is advisable to publish NPM in ES6 format leaving the platform-specifics to build chain.

Said so, in LR build stack it would be worth to include automatic build and packaging with such 3 build profiles out of the box. It will make not just code more efficient, but will eliminate browser capabilities support from developer scope. Will be happy to give a hand on that.

@sashafirsov

This comment has been minimized.

Copy link
Author

commented Feb 7, 2019

@izaera
> 2. It needs an specific build process

ES6 modules are supported out of the box by modern browsers so no need to build for those. Unfortunately LR as enterprise level software have to support not only those but also legacy browsers. In my case IE11.
The most popular build chain WebPack and Polymer are dealing with that task without any effort from developer prospective by making separate builds for IE and for Chrome. As developer I just need to expose the entry JS from one or another bundle depend of browser capabilities.

In LR liferay-npm-bundler it is not an option. It took me few days to figure out how to modify babel config to build npm dependencies with custom babel profiles. Please update the CONFIGURING LIFERAY-NPM-BUNDLER
page with comment that liferay-npm-bundler-preset-standard/config.json is a sample of .npmbundlerrc , otherwise it is impossible to grasp how to change profiles in .npmbundlerrc. Also please mention that after any changes to config should follow with build/ folder cleanup.

Unfortunately combination of presets which enabling ES6 kind of module import does not work well with liferay-standard preset. The relative path is not transpiled and since changed URL in LR is not node_module folder anymore relative path could not be resolved by LR AMD loader.

    ".babelrc": {
			"presets": ["liferay-standard","es2015"]
		},

The relative path also a pain in source code. Following line is broken there:

import './submodule/submodule';

as it renders require('./submodule/submodule');

@sashafirsov

This comment has been minimized.

Copy link
Author

commented Feb 7, 2019

However, I suspect that the real problem may be in what you are trying to do.

  1. Are you sure those Vaadin modules are intended to be loaded from an AMD loader?

Definitely not, the Polymer Elements (and Vaadin as its extension) are made as ES6 modules to be either used as is from node_modules/ subfolder or via build toolchain (WebPack or Polymer). In liferay-npm-bundler those also transpiled by wrapping into Liferay.define() which demands code to be in old (ES5 format). So if liferay-npm-bundler requires AMD as input, it should support transpilation flags so modules which are in different format could be prepared. Attempt of such config is shown in previous comment.

  1. What is the usual way to build a Vaadin project when not using the bundler?

I guess it is about ability to compile but not bundle. The transpiler changes named package to relative path package. I.e. from node_modules/some-module subfolder import '@vaadin/xxx' changed to
import "../@vaadin/xxx"

  1. How do you use those modules inside an standard webapp project?

In usual way Polymer CLI is used as is. It creates 3 bundles per browser profile. Each bundle comprise of multiple JS. Main is loaded immediately, other are loaded on demand. Those are defined by dynamic import() statement, but also could be manually tuned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.