My website has been working well before my recent change. The website front-end is on reactjs, and bundle is on aws s3. Everything is good till this point.
Now because of huge size of static bundle and also to optimize my code, I started splitting code via webpack split code, lazy loading of react component and dynamic import. I am using webpack-bundle-tracker to create bundle because my back-end is on django. This new setup is working well on my local environment.
DEV environment:
<script type="text/javascript" src="/static/frontend/main.35952edee77e6e3f52e5.bundle.js" ></script>
And this loads very well formatted code to load on my local environment:
DEV environment:
/******/ (function(modules) { // webpackBootstrap
/******/ // install a JSONP callback for chunk loading
/******/ function webpackJsonpCallback(data) {
/******/ var chunkIds = data[0];
/******/ var moreModules = data[1];
/******/
/******/
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0, resolves = [];
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
/******/ resolves.push(installedChunks[chunkId][0]);
/******/ }
/******/ installedChunks[chunkId] = 0;
/******/ }
/******/ for(moduleId in moreModules) {
/******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
/******/ modules[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if(parentJsonpFunction) parentJsonpFunction(data);
/******/
/******/ while(resolves.length) {
/******/ resolves.shift()();
/******/ }
/******/
/******/ };
But when I deploy code on heroku, and push static bundles on aws s3, it stops working. It doesn't throw any error, so I am not able to understand the reason of this issue.
Prod env
<script type="text/javascript" src="https://ecmsdjango-main.s3.amazonaws.com/staticfiles/main.54a39fc868c800757af7.bundle.js" ></script>
Further if I click on the above aws link I can see the static content, but this is not in a good format as I could see on my local environment.
Prod env
(window.webpackJsonp=window.webpackJsonp||[]).push([[0],{1003:function(e,t,n){},1004:function(e,t,n){"use strict";n.r(t);var r=n(0),a=n.n(r),o=n(81),s=n(12),i=n(38),c=n(1),l=n.n(c),u=n(14);function p(e){return(p="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function m(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function d(e,t){return!t||"object"!==p(t)&&"function"!=typeof t?function(e){if(void 0!==e)return e;throw new ReferenceError("this hasn't been initialised - super() hasn't been called")}(e):t}function h(e){return(h=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function f(e,t){return(f=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var g=function(){function i(){var e,t,a;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,i);for(var n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return d(a,(t=a=d(this,(e=h(i)).call.apply(e,[this].concat(r))),a.state={username:"",password:""},a.onSubmit=function(e){e.preventDefault(),a.props.login(a.state.username,a.state.password)},a.onChange=function(e){return a.setState((t={},n=e.target.name,r=e.target.value,n in t?Object.defineProperty(t,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[n]=r,t));var t,n,r},t))}var e,t,n;return
So basically the website doesn't load any thing (its blank) but underlying bundles have static content in it. So it appears to me that something is linked with the loader or could
be the way aws s3 loads the chunks, but I haven't got root cause yet, please help me to fix this.
For example: website is showing old version before code split, if I deploy the latest code, it will be blank.
P.S. For now I am tagging it with react js, django as well because main reason of code split was optimization of my react front-end, and bridging it with django but both of these tags can be removed.
The issue is happening because of webpack split chunks optimization config, I have removed that config from prod and it was all looking okay. I have not this extra optimization in webpack dev config.
I am marking it as an answer, because now I know the root cause and its not an aws s3 or webpack issue, and overall its no longer a problem now.
I am defining the AMD module under OSGi module. I have to read host property in AMD loader definition. how can I read the property from portal-ext.properties file?
below is sample code how I am defining the AMD module and property in portal-ext.properties file.
portal-ext.properties
# host detail
host={{host_url}}
define AMD module
Liferay.Loader.define('genelec-shopping-cart', [], function(){
const host = ""; //here i have to read the property
return{
getHost:function(){
return host;
},
};
});
You can do this with ftl or jsp, building your JS with the value embedded.
Instead of creating the whole code from a JSP you can also just build a small portion of it, adding the value to a JS variable, making it available for scripts that will load later.
Let's say you have an OSGi module which JS code, you can create a .js.jsp that will build the JS before sending it.
Using JSP to create a small portion of JS:
<%# page contentType='application/javascript' %>
//here i have to read the property -> do it in java
Liferay.Loader.define('genelec-shopping-cart', [], function(){
const host = "${read_in_java}";
return{
getHost:function(){
return host;
},
};
});
You can include it from other JSP files as:
<c:url var='url' value='/variables.js.jsp'>
<c:param name='namespace' value='${namespace}'/>
</c:url>
<script src='${url}'></script>
But as you mentioned the host, you are probably looking for something much simpler than that (especially because this is kind of a hack), using Liferay's JS api:
Liferay.ThemeDisplay.getPortalURL() and friends, docs here:
https://dev.liferay.com/de/develop/tutorials/-/knowledge_base/7-1/liferay-javascript-apis
I am new to ember. But for a particular task i need to change input path of templates to compile. i.e default is app/templates. but i want to change this path.
I have read the ember-cli-build.js file but i can edit only output path. how can i edit the input path.
My ember-cli-build.js
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function(defaults) {
var app = new EmberApp(defaults, {
// Add options here
outputPaths: {
app: {
html: 'ember_build_index.html'
}
}
});
// Use `app.import` to add additional libraries to the generated
// output files.
//
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.
app.import('bower_components/bootstrap/dist/js/bootstrap.min.js');
app.import('bower_components/bootstrap/dist/css/bootstrap.min.css');
app.import('bower_components/bootstrap/dist/css/bootstrap.css.map');
return app.toTree();
};
You have to change templates directory path for the ember app being built.
To check your current templates directory path, check app.trees.templates._directoryPath in your ember-cli-build.js by log it to console using console.log(app.trees.templates._directoryPath) .
Now, if you want your ember build to have templates from 'app/templates/mobile' (in your case), just change:
app.trees.templates._directoryPath = 'app/templates/mobile' in ember-cli-build.js before it returns app.toTree();
The node_module which constructs tree for templates is at 'node_modules/ember-cli/lib/broccoli/ember-app.js' at line no. 724 where it accesses 'this.trees.templates' in which this is the instance of your app.
With the excellent broccoli-stew I can take a look at the exported application tree:
/* global require, module */
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
var log = require('broccoli-stew').log;
var debug = require('broccoli-stew').debug;
var app = new EmberApp();
// Use `app.import` to add additional libraries to the generated
// output files.
//
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.
app.import('bower_components/ember-i18n/lib/i18n.js');
app.import('bower_components/raphael/raphael.js');
var finalTree = log(app.toTree());
module.exports = finalTree;
With this I get a very clean tree-like output of my application:
[ 'assets/app.js',
'assets/app.map',
'assets/app.scss',
...
'assets/vendor.css',
'assets/vendor.js',
'assets/vendor.map',
'crossdomain.xml',
'index.html',
'robots.txt',
'testem.js',
'tests/index.html' ]
I see that in that tree we have, among other files, a vendor.js and an app.js modules (as expected), but I do not know what packages are put into each of them.
I have the feelling I am missing one in my frontend (in this case, raphael.js), so I would like to verify that ember-cli (via EmberApp) has indeed done what I asked for (namely, include the raphael.js, probably in vendor.js)
Taking a direct look at app.js or vendor.js is not feasible (too big / don't know what to look for). I want a simple tree-like display of the files that have been included by EmberApp into vendor.js / app.js, in the same (similar) format that broccoli-stew is providing.
Is this possible? How?
To quote http://www.ember-cli.com/asset-compilation/#configuring-output-paths:
Assets Output File
JavaScript files you import with app.import() /assets/vendor.js
So although that is not a nice tree view, you should be fine :-)
I get the error GET localhost:8080/scripts/templates/home/homeTemplate.html 404 (Not Found)
Not sure why this is happening. Based on this tutorial I feel like files are in the right place. http://backbonetutorials.com/organizing-backbone-using-modules/
The github repository is here https://github.com/natecraft1/backbone-widget
I reference the template like this
'text!templates/home/homeTemplate.html'
from app/templates/home...
Modify the scripts/main.js as follows.
require.config({
paths: {
jquery: 'libs/jquery',
underscore: 'libs/underscore',
backbone: 'libs/backbone',
templates: '../templates' // added
}
});
require(['app'], function(App) {
App.initialize();
});
By setting the templates as above,
if the module ID starts with "templates",
requirejs load the module from the templates directory
Without the above templates setting, requirejs load any module IDs from scripts directory, which contains main.js source code. Thus the text!templates/home/homeTemplate.html is interpreted as wrong URL scripts/templates/home/home/homeTemplate.html.
If you do not want to modify the main.js script,
you can specify the correct location of homeTemplate.html by
replacing the 'text!templates/...' with
'text!../../../templates/home/homeTemplate.html' or
'text!/../templates/home/homeTemplate.html'