Foros de discusión

Add NPM Module to AMD Loader

thumbnail
Severin Rohner, modificado hace 7 años.

Add NPM Module to AMD Loader

Junior Member Mensajes: 43 Fecha de incorporación: 28/01/14 Mensajes recientes
Hi guys
I'm working on a Liferay frontend project. We use some small JS Libraries like Bricks.js. How can I create a OSGI module with the given JavaScript file? I created a new module with following files
META-INF/resources/Bricks.es.js:
import bricks from 'bricks.js'
export default bricks;


bnd.bnd:
Bundle-Name: dep-bricks
Bundle-SymbolicName: com.clavisit.clavisit.dependency.bricks
Bundle-Version: 1.7.0
-includeresource: package.json
Web-ContextPath: /dep-bricks


package.json:
{
  "dependencies": {
    "bricks.js": "^1.7.0"
  },
  "devDependencies": {
    "babel-plugin-transform-object-rest-spread": "*",
    "babel-preset-es2015-rollup": "*",
    "browser-sync": "*",
    "del": "*",
    "gulp": "*",
    "mkdirp": "*",
    "node-notifier": "*",
    "rollup": "*",
    "rollup-plugin-babel": "*",
    "rollup-plugin-commonjs": "*",
    "rollup-plugin-node-resolve": "*",
    "rollup-plugin-uglify": "*"
  },
  "name": "dep-bricks",
  "version": "1.7.0"
}


The module is available in the portal, but if I run the code
Liferay.Loader = Loader;  // https://web.liferay.com/de/community/forums/-/message_boards/message/86192850
require('dep-bricks/Bricks.es', function(BricksModule) {
    var Bricks = BricksModule.default();
}, function(error) {
      console.error(error);
});
I get an error of a missing file http://localhost:8080/combo/?browser....&bricks.js/src/bricks.js
This is the included file from the npm module and it's available at http://localhost:8080/combo/?browser...&/o/dep-bricks/bricks.js/src/bricks.js

How can I fix the OSGI module that it loads the npm dependency in the combo URL?
thumbnail
Fernando Garcia, modificado hace 7 años.

RE: Add NPM Module to AMD Loader

New Member Mensajes: 13 Fecha de incorporación: 12/04/11 Mensajes recientes
thumbnail
Severin Rohner, modificado hace 7 años.

RE: Add NPM Module to AMD Loader

Junior Member Mensajes: 43 Fecha de incorporación: 28/01/14 Mensajes recientes
Hi Fernando
Thanks for the links.

In build.gradle I add:
configJSModules {
	configVariable = ""
	ignorePath = false
	moduleExtension = ""
	moduleFormat = "/_/g,-"
	include "**/*.js*"
}


Now are all the npm dependencies listed in the config.json:
{
    "dep-bricks@1.7.0/Bricks.es": {
        "dependencies": ["exports", "bricks.js/src/bricks"],
        "path": "dep-bricks@1.7.0/Bricks.es.js"
    },
    "dep-bricks@1.7.0/knot.js/dist/knot.module": {
        "dependencies": ["exports"],
        "path": "dep-bricks@1.7.0/knot.js/dist/knot.module.js"
    },
    "dep-bricks@1.7.0/bricks.js/src/bricks": {
        "dependencies": ["exports", "knot.js/dist/knot.module"],
        "path": "dep-bricks@1.7.0/bricks.js/src/bricks.js"
    }
}


You see, the npm module dependencies are included without dep-bricks/ prefix, but in the JavaScript code it's define with dep-bricks@1.7.0/.
bricks.js (from the npm):
Liferay.Loader.define("dep-bricks@1.7.0/bricks.js/src/bricks", ['exports', 'knot.js/dist/knot.module'], function (exports, _knot) {
  'use strict';
  ...


Does anyone have a hint for me?
thumbnail
Chema Balsas, modificado hace 7 años.

RE: Add NPM Module to AMD Loader

Regular Member Mensajes: 127 Fecha de incorporación: 25/02/13 Mensajes recientes
Hey Severin,

Do you have a repo I could clone to run some tests?

The prefix should be solvable by aliasing your modules, either manually (using a config.js file and calling the Liferay.Loader.addModule method) or automatically via the Liferay-Export-JS-Submodules bnd header.
thumbnail
Severin Rohner, modificado hace 7 años.

RE: Add NPM Module to AMD Loader

Junior Member Mensajes: 43 Fecha de incorporación: 28/01/14 Mensajes recientes
Hi Chema
I created a repo: https://github.com/severinrohner/js-module-workspace
I hope it works. If you run the JS code from the readme.md file (Liferay 7 GA 3), there should be a get error for the file http://localhost:8080/combo/?browserId=other&minifierType=&languageId=de_DE&b=7003&t=1486537328404&bricks.js/src/bricks.js (see attachment)
This is the imported bircks.js file in my Bicks.es.js
thumbnail
Chema Balsas, modificado hace 7 años.

RE: Add NPM Module to AMD Loader

Regular Member Mensajes: 127 Fecha de incorporación: 25/02/13 Mensajes recientes
Hey Severin,

All you really should need is to add the Liferay-Export-JS-Submodules header to your bnd.bnd file like this:

Liferay-Export-JS-Submodules: *

This will create aliases for brick.js and knot.js, so those imports will go out without the prefixes.

Unfortunately, while testing it out, I uncovered this issue in the Liferay AMD Loader. If you rename both brick.js and knot.js folders inside node_modules to just brick and knot, then all the modules should load properly.

I think you'll also need to include BabelHelpers, but that's a different story ;)
thumbnail
Severin Rohner, modificado hace 7 años.

RE: Add NPM Module to AMD Loader

Junior Member Mensajes: 43 Fecha de incorporación: 28/01/14 Mensajes recientes
Hi Chema
Thanks for your quick answer. I pushed a new version to my Github repo with the bnd.bnd change (as you wrote) and a new class to export the clipboard from Zeno Rocha, to prevent babel and folder name issues.

But it doesn't work, the dependencies &tiny-emitter.js&good-listener.js are missing if I call
    Liferay.Loader = Loader;  
    
    require('dep-bricks/Clipboard.es', function(module) {
     console.log(module.default);
     // Use of Bricks
     // https://github.com/callmecavs/bricks.js
     
    }, function(error) {
        console.error(error);
    });


There is a log in tomcat:
15:34:15,865 ERROR [http-nio-8080-exec-10][ComboServlet:89] java.lang.IllegalArgumentException: Path tiny-emitter.js does not start with a "/" character
java.lang.IllegalArgumentException: Path tiny-emitter.js does not start with a "/" character
        at org.apache.catalina.core.ApplicationContext.getRequestDispatcher(ApplicationContext.java:454)
        at org.apache.catalina.core.ApplicationContextFacade.getRequestDispatcher(ApplicationContextFacade.java:221)
        at com.liferay.portal.servlet.ComboServlet.getResourceRequestDispatcher(ComboServlet.java:409)
        at com.liferay.portal.servlet.ComboServlet.doService(ComboServlet.java:221)
        at com.liferay.portal.servlet.ComboServlet.service(ComboServlet.java:86)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:119)
        at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:142)
        at com.liferay.portal.servlet.filters.language.LanguageFilter.processFilter(LanguageFilter.java:82)
        at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:48)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:207)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:112)
        at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:142)
        at com.liferay.portal.servlet.filters.gzip.GZipFilter.processFilter(GZipFilter.java:125)
        at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:48)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:207)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:112)
        at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:142)
        at com.liferay.portal.servlet.filters.cache.CacheFilter.processFilter(CacheFilter.java:428)
        at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:48)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:207)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:112)
        at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:142)
        at com.liferay.portal.servlet.filters.etag.ETagFilter.processFilter(ETagFilter.java:86)
        at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:48)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:207)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:112)
        at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:142)
        at com.liferay.portal.servlet.filters.header.HeaderFilter.processFilter(HeaderFilter.java:96)
        at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:48)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:207)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:112)
        at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:142)
        at com.liferay.portal.sharepoint.SharepointFilter.processFilter(SharepointFilter.java:88)
        at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:48)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:207)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:112)
        at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:142)
        at com.liferay.portal.servlet.filters.virtualhost.VirtualHostFilter.processFilter(VirtualHostFilter.java:257)
        at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:48)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:207)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:112)
        at com.clavisit.brw.radar.hook.redirect.CustomFilter.doFilter(CustomFilter.java:59)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:207)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:112)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDirectCallFilter(InvokerFilterChain.java:188)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:96)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDirectCallFilter(InvokerFilterChain.java:188)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:96)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDirectCallFilter(InvokerFilterChain.java:168)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:96)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDirectCallFilter(InvokerFilterChain.java:168)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:96)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDirectCallFilter(InvokerFilterChain.java:188)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:96)
        at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilter.doFilter(InvokerFilter.java:99)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)
15:34:16,297 ERROR [http-nio-8080-exec-10][status_jsp:955] Path tiny-emitter.js does not start with a "/" character
15:39:29,699 ERROR [http-nio-8080-exec-5][ComboServlet:89] java.lang.IllegalArgumentException: Path tiny-emitter.js does not start with a "/" character
java.lang.IllegalArgumentException: Path tiny-emitter.js does not start with a "/" character
        at org.apache.catalina.core.ApplicationContext.getRequestDispatcher(ApplicationContext.java:454)
        at org.apache.catalina.core.ApplicationContextFacade.getRequestDispatcher(ApplicationContextFacade.java:221)
        at com.liferay.portal.servlet.ComboServlet.getResourceRequestDispatcher(ComboServlet.java:409)
        at com.liferay.portal.servlet.ComboServlet.doService(ComboServlet.java:221)
        at com.liferay.portal.servlet.ComboServlet.service(ComboServlet.java:86)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
thumbnail
Chema Balsas, modificado hace 7 años.

RE: Add NPM Module to AMD Loader

Regular Member Mensajes: 127 Fecha de incorporación: 25/02/13 Mensajes recientes
Hey Severin,

First of all, I want to clarify that npm support, understood in the broad sense, is not something we have right now. Only es6-friendly modules (that is, modules with sources in es6 and a jsnext:main property in their package.json) are suitable to get hooked directly into the out of the box build system.

For others, a manual process is required to define the modules and configure the loader properly.

I gave this specifically a try yesterday, and the sad truth is that none of those 3 libraries are easily introduced in the out of the box build process. The reasons are:
  • Both tiny-emitter.js and knot.js are not es6-friendly modules
  • Even if clipboard.js is written in es6, the sources are excluded from the npm module

There are ways to try to get them to fall in line, but I think the safest bet should be to:
  • Host a vendor version of clipboard.js
  • Make use of the config.js option to configure it as a global library (exports: 'Clipboard')
  • Hide the Liferay AMD Loader to make sure it loads as a global library


Hope this helps, and sorry for the confussion in this aspect emoticon
thumbnail
Severin Rohner, modificado hace 7 años.

RE: Add NPM Module to AMD Loader

Junior Member Mensajes: 43 Fecha de incorporación: 28/01/14 Mensajes recientes
Chema Balsas:

First of all, I want to clarify that npm support, understood in the broad sense, is not something we have right now. Only es6-friendly modules (that is, modules with sources in es6 and a jsnext:main property in their package.json) are suitable to get hooked directly into the out of the box build system.


Hi Chema
This are bad news and hard to believe. I think this is like Liferay would not support maven central repository for the java stuff.
Anyway, I created my own module for the Bricks.js. Copy paste of the source code (=> all path are relative), add the dev. dependencies and it works fine. But this is a nightmare if a library will have larger dependencies or the project is big.

So one question I still have: How can I import/use a module that's not in the workspace? Here are two examples:

I created a module with the Slick code (http://kenwheeler.github.io/slick/). Slick needs jQuery. At the moment I just use jQuery from global and hope that it's loaded at that moment. The right way should be to import the jQuery in the module. Liferay AMD loader should then first loads jQuery and afterward my code.
How can I import the jQuery that is loaded in the portal?

If I create a stand alone (general) module to use in different project, how can I use it in my project Liferay workspace?

I still hope that we can use the Liferay AMD Loader and don't need put all library to global space.

Thanks for your help Chema and the patience with me ;-)

Severin