Dojo Build with NLS - requireLocalization(..) fail? - internationalization

My question, while at first somewhat similar to this one, seems to be a more basic question - and might be signaling a bug in the build system. I've created a custom build for my dojo application. I only build one layer right now, here's what the profile script/object looks like:
dependencies = {
stripConsole: "all",
action: "release",
optimize: "shrinksafe",
releaseName: "myProject",
// list of locales we want to expose
localeList: "en-gb,en-us,de-de",
layers: [
{
// Name: a relative path from the dojo.js in the desination directory.
name: "../../myProject.js",
dependencies: [
"myPackage.MyDataStore",
// MyWidget depends on a few other widgets, and has its own
// translation files.
"myPackage.MyWidget"
]
}
],
prefixes: [
// These paths are relative to the location of dojo.js
[ "dijit", "../dijit" ],
[ "dojox", "../dojox" ],
[ "myPackage", "../../../src/myPackage" ]
]
}
When I run a build with that description it outputs files in the following directory structure:
release/
release/myProject/
release/myProject/dijit/
... dijit ...
release/myProject/dojo/
... dojo ...
release/myProject/dojox/
... dojox ...
release/myProject/myPackage/
... my custom package ...
release/nls/
myProject_en-us.js
myProject_de.js
etc..
../myproject.js
../myProject.js.uncompressed.js
Finally, in my test HTML page - I've got the following:
<script type="text/javascript">
var djConfig = {
debug: true,
parseOnLoad: false,
modulePaths: { // paths to directories in relation to dojo's location.... hurr.
'myPackage': '../myPackage',
'dojox': '../dojox',
'dijit': '../dijit'
}
};
</script>
<script type="text/javascript" src="./release/myProject/dojo/dojo.js.uncompressed.js"></script>
<script type="text/javascript" src="./release/myProject.js.uncompressed.js"></script>
<script type="text/javascript">
dojo.addOnLoad(function(){
dojo.require('myPackage.MyDataStore');
dojo.require('myPackage.MyWidget');
var store = new myPackage.MyDataStore();
var widget = new myPackage.MyWidget({
store: store
}, dojo.byId('testWidget'));
widget.startup();
});
</script>
But unfortunately, Firebug spits this out at me:
Bundle not found: MyWidget in myPackage , locale=en-us
What I Think is Happening
I've traced through some of the code leading up to the above error and it seems like the dojo.i18n._preloadLocalizations() call at the end of the file doesn't actually load in the correct nls file from ./release/nls.
Any idea how to fix this without resorting to manually including the nls files with <script> tags?

It's a bug of dojo, you should not use '..' in your layers name in case it will generate a NLS package.
please refer to http://bugs.dojotoolkit.org/ticket/5225

Related

RequireJS data-main does not load from html files at different paths

Using RequireJS successfully for a single page application for quite some time. Finally adding JS unit tests to exercise model classes. I have a single config for src modules and another for test modules. (I want to keep test files out of the shipping distribution)
I can load src from index.html and test from LocationTest.html only if both files are in the same top-level folder. I would like to move LocationTest.html inside the test folder, but no change to data-main or the test config file seems to work.
Here is the file layout for the happy path...
/www
- index.html
- LocationTest.html
- js
- src
- lib
- require.js
- require_src_config.js
- require_main.js
- require_test_config.js
- require_test.js
- model
- Location.js
- (other src model classes)
- test
- lib
- (jasmine libs)
- model
- LocationTest.js
- (other test model classes eventually)
index.html
...
<script type='text/javascript' data-main='js/src/lib/require_main' src='js/src/lib/require.js'></script>
...
LocationTest.html
...
<script type='text/javascript' data-main='js/src/lib/require_test' src='js/src/lib/require.js'></script>
...
js/src/lib/require_src_config.js
requirejs.config({
// Base URL for main application
baseUrl: 'js',
// Shortcuts to modules relative to baseUrl
paths: {
Location: 'src/model/Location'
(many other modules...)
}
});
js/src/lib/require_test_config.js
requirejs.config({
baseUrl: 'js',
// Paths (no extension)
paths: {
// Tests
LocationTest: 'test/model/LocationTest',
// Framework
jasmine: 'test/lib/jasmine/jasmine',
jasmineHtml: 'test/lib/jasmine/jasmine-html',
jasmineBoot: 'test/lib/jasmine/boot',
},
// Make external libraries compatible with requirejs (AMD)
shim: {
jasmineHtml: {
deps : ['jasmine']
},
jasmineBoot: {
deps : ['jasmine', 'jasmineHtml']
}
}
});
js/src/lib/require_main.js
requirejs(['./require_src_config'], function (require_src_config) {
(Application Code)
});
js/src/lib/require_test.js
requirejs(['./require_src_config'], function (require_src_config) {
requirejs(['./src/lib/require_test_config'], function (require_test_config) {
requirejs(['jasmineBoot'], function (require) {
requirejs(['LocationTest'], function (LocationTest) {
// Trigger Jasmine
window.onload();
});
});
});
});
The above all works, although I do not understand why I had to revise the path to require_config_test.js in require_test.js. The baseUrl for both configs is 'js'.
I would like to move LocationTest.html to js/test/model.
1) What should my data-main be set to?
2) How (and why) does this impact require_test.js settings?
3) Is there a better way to nest (or not) the configs for src and test to ensure src gets loaded first?
I was hoping to only have to set data-main to the path of the file with the entrypoint and be flexible to move things around. Thanks for your help!

How to create a Fusebox project with multiple html pages?

I'm new to bundlers and am currently learning about Fusebox. I really like it so far except that I can't figure out how to use it for a multi-page project. So far I've only been able to find a tutorial on how to do this using webpack, not for fusebox.
Input files in src folder:
index.html
index2.html
index.ts
Desired output in dist folder:
app.js
vendor.js
index.html
index2.html
Actual output in dist folder:
app.js
vendor.js
index.html
Here is my config in the fuse.js file:
Sparky.task("config", () => {
fuse = FuseBox.init({
homeDir: "src",
output: "dist/$name.js",
hash: isProduction,
sourceMaps: !isProduction,
plugins: [
[SassPlugin(), CSSPlugin()],
CSSPlugin(),
WebIndexPlugin({
title: "Welcome to FuseBox index",
template: "src/index.html"
},
WebIndexPlugin({
title: "Welcome to FuseBox index2",
template: "src/index2.html"
},
isProduction && UglifyJSPlugin()
]
});
// vendor should come first
vendor = fuse.bundle("vendor")
.instructions("~ index.ts");
// out main bundle
app = fuse.bundle("app")
.instructions(`!> [index.ts]`);
if (!isProduction) {
fuse.dev();
}
});
Setting WebIndexPlugin twice within plugins doesn't work. What is the correct way to set up a multi-html page project with fusebox?
The WebIndexPlugin can not be configured, to output more than one html file.
But if you don't use a hash for the generated bundles (e.g.: output: "dist/$name.$hash.js"), you don't need the WebIndexPlugin -- you can remove it completly from the plugins option. Because you already know the names of the generated bundles (vendor.js and app.js) you can just include the following lines
<script src="vendor.js"></script>
<script src="app.js"></script>
instead of the placeholder $bundles.
If you want, that both html files are copied from your src directory into your dist directory, you can add the following lines to your fuse.js script:
const fs = require('fs-extra');
fs.copySync('src/index.html', 'dist/index.html');
fs.copySync('src/index2.html', 'dist/index2.html');
Note: Don't forget to add fs-extra:^5.0.0 to your package.json
Might not been the case when the question was asked, but WebIndexPlugin now can be specified multiple times and also takes optional bundles parameter where list of bundles to be included in html can be specified (all bundles are included by default).
For example 2 html files (app1.html, app2.html) where each includes a common library (vendor.js), and different entry points (app1.js and app2.js)
app1.html
vendor.js
app1.js
app2.html
vendor.js
app2.js
Config would look like this:
const fuse = FuseBox.init({
homeDir : "src",
target : 'browser#es6',
output : "dist/$name.js",
plugins: [
WebIndexPlugin({
target: 'app1.html',
bundles:['vendor', 'app1']
}),
WebIndexPlugin({
target: 'app2.html',
bundles:['vendor', 'app2']
})
]
})
// vendor bundle, extracts dependencies from index1 and index2:
fuse.bundle("vendor").instructions("~[index1.ts,index2.ts]")
// app1 and app2, bundled separately without dependencies:
fuse.bundle("app1").instructions("!>index1.ts")
fuse.bundle("app2").instructions("!>index2.ts")

Bootstrap/Brunch difficulty with Phoenix

I am trying to compile bootstrap with Brunch in Phoenix. I have deployed a simple collapse nav to heroku, but the nav button doesn't activate on resize: https://hidden-wildwood-14271.herokuapp.com/test
If you look at the <head> in the source code, you'll see this:
<link rel="stylesheet" href="/css/app.css">
<script src="/js/app.js"></script>
<!--<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">-->
<!--<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>-->
When these links/scripts are uncommented, this nav bar works just fine (assuming you're doing this from a local/non-https, like heroku in production). Instead I have to use the Brunch-compiled css/app.css and js/app.jsat the top. Those file contain exactly the same code as the referenced files in comments (bootstrap css, jquery/bootstrap js).
I'm also getting this error in the console, and have no idea what it means:
Uncaught Error: Cannot find module 'web/static/js/app' from '/'
Also, this is what my brunch-config looks like (very little difference from default configuration):
exports.config = {
// See http://brunch.io/#documentation for docs.
files: {
javascripts: {
joinTo: "js/app.js"
// To use a separate vendor.js bundle, specify two files path
// http://brunch.io/docs/config#-files-
// joinTo: {
// "js/app.js": /^(web\/static\/js)/,
// "js/vendor.js": /^(web\/static\/vendor)|(deps)/
// }
//
// To change the order of concatenation of files, explicitly mention here
// order: {
// before: [
// "web/static/vendor/js/jquery-2.1.1.js",
// "web/static/vendor/js/bootstrap.min.js"
// ]
// }
},
stylesheets: {
joinTo: "css/app.css",
order: {
after: ["web/static/css/app.css"] // concat app.css last
}
},
templates: {
joinTo: "js/app.js",
order: {
before: ["web/static/js/app.js"]
}
}
},
conventions: {
// This option sets where we should place non-css and non-js assets in.
// By default, we set this to "/web/static/assets". Files in this directory
// will be copied to `paths.public`, which is "priv/static" by default.
assets: /^(web\/static\/assets)/
},
// Phoenix paths configuration
paths: {
// Dependencies and current project directories to watch
watched: [
"web/static",
"test/static"
],
// Where to compile files to
public: "priv/static"
},
// Configure your plugins
plugins: {
sass: {
options: {
// Use includePaths to allow sass to load files outside your tree
// For example, from node_modules
//includePaths: ['app/css']
}
},
postcss: {
processors: [
require('autoprefixer')(['last 8 versions'])
]
},
babel: {
// Do not use ES6 compiler in vendor code
ignore: [/web\/static\/vendor/]
}
},
modules: {
autoRequire: {
"js/app.js": ["web/static/js/app"]
}
},
npm: {
enabled: true
}
};

Can't figure out how to inject assets using assets-webpack-plugin

Clearly I'm missing something here, I'm trying to prevent caching using assets-webpack-plugin but I seem to have trouble understanding their documentation Here's what I did:
My Config
...
import assetPlugin from 'assets-webpack-plugin';
...
...
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: 'bundle.[hash].js'
},
...
plugins: [
new assetPlugin(),
...
That successfully generates a file in my root called webpack-assets.json which contains:
{"main":{"js":"/bundle.dbe7d464b6bdec429d82.js"}}
In their documentation the only example they give on how to even generate anything in the HTML template looks like this:
new AssetsPlugin({includeManifest: 'manifest'})
// assets.json:
// {entries: {manifest: {js: `hashed_manifest.js`, text: 'function(modules)...'}}}
//
// Your html template:
// <script>
// {assets.entries.manifest.text}
// </script>
which I take it to mean, using my generated file: {webpack-assets.main.js}
So I add this in my HTML template:
...
<body>
<div id="app" ></div>
{webpack-assets.main.js}
...
I even tried with the commented out:
...
// {webpack-assets.main.js}
...
Curly brackets don't get replaced with anything so the HTML page just looks like .
{webpack-assets.main.js}
Clearly I'm missing something here that documentation, I'm guessing, assumed I knew already or I completely missed the ball on this.

Inject kendo ui with requirejs

The documentation on kendo ui and requirejs seems to miss some stuff.
They tell me how to use kendo.web.min which have everything included:
http://www.kendoui.com/blogs/teamblog/posts/13-05-08/requirejs-fundamentals.aspx
(search for keyword 'shim')
but I am not interested in adding the big 2MB kendo.web.min script, I just want to shim the
kendo.grid.min but this file has a dependency to kendo.data.min which again has a dependency
to kendo.core.min.
How can I tell requirejs to load also kendo.data.min and kendo.core.min before kendo.grid.min is loaded and after jquery has been loaded. I just guess this would be the correct order.
This is what I have tried from the above telerik link:
requirejs.config({
paths: {
'text': '../Scripts/text',
'durandal': '../Scripts/durandal',
'plugins': '../Scripts/durandal/plugins',
'transitions': '../Scripts/durandal/transitions',
'knockout': '../Scripts/knockout-2.3.0',
'jquery': '../Scripts/jquery-2.0.3',
'kendoGrid': '../Scripts//kendo.grid.min',
},
shim: {
"kendoGrid": {
deps: ["jquery"]
}
}
});
What is the correct way of defining the kendo dependencies like kendo.data and kendo.core ?
At the moment I am getting an exception on application startup from durandal in the systems.js saying:
"Failed to load composed module (viewmodels/DocumentBrowser). details: The property \"jQuery\" of an undefined or null reference can not be 'accessed'.
I know this error is not directly about kendo, but since I introduced kendo ui with requirejs in the DocumentBrowser module I get this exception!
UPDATE
According to CodingWhitSpike`s advise I have changed my requirejs configuration:
requirejs.config({
paths: {
'text': '../Scripts/text',
'durandal': '../Scripts/durandal',
'plugins': '../Scripts/durandal/plugins',
'transitions': '../Scripts/durandal/transitions',
'knockout': '../Scripts/knockout-2.3.0',
'jquery': '../Scripts/jquery-2.0.3',
'moment': '../Scripts/moment',
k: "../Scripts/kendo"
}
});
define(['durandal/app', 'plugins/dialog', 'knockout', 'services/dataservice', 'plugins/router', 'moment', 'k/kendo.grid.min'],
function (app, dialog, ko, dataservice, router, moment, kendoGrid) {
$("#grid").kendoGrid(...); => kendoGrid is instantiated and it works :)
});
This is taken from the official Kendo docs at http://docs.kendoui.com/getting-started/using-kendo-with/using-kendo-with-requirejs
<!-- first, load RequireJS -->
<script src="require.js"></script>
<!-- configure RequireJS with two logical paths:
- "app/" will be used for your files
- "k/" will be for Kendo UI modules -->
<script>
requirejs.config({
paths: {
app: "/path/to/your/files",
k: "http://cdn.kendostatic.com/VERSION/js"
}
});
require([
"http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js",
"app/foo",
"app/bar",
"k/kendo.menu.min",
"k/kendo.grid.min"
], initApp);
function initApp() {
// main entry point of your application
}
</script>
Assuming that kendo has set up dependencies of their modules correctly, setting up a path like k: "http://cdn.kendostatic.com/VERSION/js which points to the modules directory (NOT one individual module) and use a module in like k/kendo.grid.min should all that's required.

Resources