Error: defineAlreadyDefined after applying dojo build - dojo

I have created own build profile following the instructions from http://www.sitepen.com/blog/2012/06/11/dgrid-and-dojo-nano-build/. I've created bootstrap layer for dojo:
'dojo/dojo': {
include: ['dojo/dojo', 'dojo/domReady', 'dojo/_base/declare'],
boot: true,
customBase: true
},
I've noticed also, that if I skip definition of this layer, the bigger dojo package is created, so the modules included in the second layer are duplicated.
The second layer contains GridX modules, dijit controls and everything else from Dojo that is used:
'dojo/dojo-all': {
include: ["dojo/on", "dojo/dom-attr", "dojo/dom-class", "dojo/query", "dojo/_base/lang", "dojo/request/xhr", "dojo/parser", "dojo/_base/connect", "dojo/DeferredList", "dojo/store/Memory", "dojo/store/Observable",
"dijit/registry","dijit/form/TextBox", "dijit/form/Textarea", "dijit/form/ComboBox", "dijit/form/FilteringSelect", "dijit/form/CheckBox", "dijit/form/Button",
"gridx/core/model/cache/Sync", "gridx/Grid", "gridx/modules/SingleSort", "gridx/modules/ColumnResizer", "gridx/modules/Pagination", "gridx/modules/pagination/PaginationBar", "gridx/modules/CellWidget", "gridx/modules/Edit", "gridx/modules/Persist", "gridx/modules/Filter", "gridx/modules/filter/FilterBar", "gridx/modules/filter/QuickFilter", "gridx/modules/HiddenColumns"],
exclude: ['dojo/dojo', 'dojo/domReady', 'dojo/_base/declare'],
boot: true,
customBase: false
},
The application starts correctly, and it makes only a request to layered resources, however there is an error in FireBug console:
Error: defineAlreadyDefined
makeError()
dojo-all.js (Zeile 28)
I think this is because the declare module is loaded twice: first with dojo.js bootstrap, defined from HTML file. Second, from dojo-all.js layer, loaded dynamically via require.
There must be some flow in my approach based on cited article, or the article is adapted to the older version of Dojo (I'm using version 1.9).
What is the error here? How should the layers be correctly defined? How can I instruct dojo build not to overwrite the dojo.js bootstrap? Or the exclude is not correctly declared - if so, how should it be declared?

Setting boot: true causes the loader to be included. Only set boot: true on the layer that you want to include the define function.

Related

Vue.js 3 extension breaks while using "vue-cli-service build" due to unsafe-eval

I am developing a chrome extension using vue 3, vue-router and vuex based on Kocal's project which uses vue-cli under the hood. I used whenever possible Single File Components with extensive use of vue bindings.
Everything works perfect on development mode but I recently tried to build the application for production and I encountered this error with partial rendering:
chunk-vendors.f6de00a6.js:11 EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self'".
After a few days of digging, my understanding is that either webpack or vue compiling system is messing with CSP by referring/injecting code through eval scripts. As I am fairly new to this, it's hard for me to read to distinguish what I can do.
I tried different approaches:
defining $vue alias to a runtime only build in vue.config.js (supposedly removing unsafe eval by having code compiled before runtime but ending with a new error: Uncaught TypeError: Object(...) is not a function for o=Object(n["withScopeId"])("data-v-21ae70c6");)
using render() function at root
adding "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", to manifest.json
switching a component to render() to see if I have better chance with the partial rendering, but ending up with nothing being displayed although having console.log from render being executed.
Adding a config to chainWebpack splitting manifest and inline manifest on vue.config
What puzzles me is that I can't shake off the unsafe-eval, with at best a partial display, at worst a blank page. Bindings seem to be shaken off regardless and using a router-link to change page will give a blank page.
Edit: After digging through compiled code from webpack and setting minimize opt to false, it seems the error comes from a vendor: vue-i18n
The eval is likely coming from Webpack, due to an issue with global scoping.
see link for more detail https://mathiasbynens.be/notes/globalthis
Could you try adding this configuration to vue.config.js
module.exports = {
configureWebpack: {
node: {
global: false
},
plugins: [
new webpack.DefinePlugin({
global: "window"
})
]
}
};
tl;dr: Check your dependencies/packages, including those you wouldn't think they use unsafe-eval.
After digging into webpack internals and components building for vue3, here are the takeaways:
using Single File Components and default vue-cli config is ok as it will indeed just need vue runtime, so no unsolicited unsafe-eval
webpack config as below works:
module.exports = {
configureWebpack: {
plugins: [
new webpack.DefinePlugin({
global: "window" // Placeholder for global used in any node_modules
})
]
},
...
};
// Note that this plugin definition would break if you are using "unit-mocha" module for vue-cli
In the end, the issue was a dependency I was using for i18n vue-i18n#next, after removing it and switching to chrome's i18n way, it's now working.

Dojo requesting already inlined Dijit templates --Google Closure build

I already asked this question on StackOverflow, the solution was supposed to have been patched in commits :
89bf2786e322323293f52917223aa24db7649951
and
783da4030bf9e727bfb4fc874b59f77521545264
But even after doing some extensive testing with this setup :
Dojo / DojoX / Dijit 1.8.3
Util in it's latest version (master branch on GitHub)
I keep getting the same issue.
The issue is the following :
After building my application with the util build.sh script.
My profile is :
var profile = {
basePath: '../src/',
action: 'release',
cssOptimize: 'comments',
mini: true,
internStrings: true,
optimize: 'closure',
layerOptimize: 'closure',
stripConsole: 'none',
selectorEngine: 'acme',
layers: {
'dojo/dojo': {
include: [ 'dojo/dojo', 'dojo/i18n', 'dojo/domReady', 'app/main', 'app/run', 'app/widgets/Application'],
boot: true,
customBase: true
},
},
staticHasFeatures: {
'dojo-trace-api': 0,
'dojo-log-api': 0,
'dojo-publish-privates': 0,
'dojo-sync-loader': 0,
'dojo-xhr-factory': 0,
'dojo-test-sniff': 0
}
};
and running :
java -Xms256m -Xmx256m -cp ../shrinksafe/js.jar:../closureCompiler/compiler.jar:../shrinksafe/shrinksafe.jar org.mozilla.javascript.tools.shell.Main ../../dojo/dojo.js baseUrl=../../dojo load=build --require "$myConfig" --profile "$myProfile" --releaseDir "$myReleaseDir" $#
1) My Dijit templates are inlined in the output file like they should, but when running the app, Dojo is still making Ajax requests for the already inlined templated !
2*) The nls directory is placed in the wrong directory (dojo directory in place of the root directory) and has to be moved. (I'm not sure if this is related to the bug I encounter.)
Inline format is :
"url:path/to/my/template.html":'<p>Some escaped HTML</p>'
Template require format :
dojo/text!./path/to/my/template.html
Thanks in advance !
I also had similar problem. In my application i used multiple dijit widgets and to avoid many AJAX calls I created a layer.
layers:{
'dijit/mydijit':{
include:["dijit/_base","many dijit widgets"]
}
After including dijit/mydijit.js in my application the browser kept on making AJAX call for dijit/_base
To solve this problem i added dijit/_base as dependency of dijit/mydijit layer
layers:{
'dijit/mydijit':{
include:["dijit/_base","many dijit widgets"],
dependecies:["dijit/_base"]
}
After this there are no requests for dijit/_base.
Hope this helps you :)

dojo looking for build.js in wrong path

I am trying to run my dojo project on a local Tomcat (7.0) server using Eclipse Juno 64bit as a dev environment.
I ran into a problem yesterday concerning how dojo assumes where files are stored within the source tree.
Below is a firebug log showing the issue:
304 Not Modified 23ms dojo.js (Line 295)
GET http://localhost:8080/src/dojo-18/dojo/parser.js
304 Not Modified 46ms dojo.js (Line 295)
GET http://localhost:8080/src/dojo-18/dojo/util.js
404 Not Found 24ms dojo.js (Line 295)
"NetworkError: 404 Not Found - http://localhost:8080/src/dojo-18/dojo/util.js"
The first 2 paths (and a lot before them) are loaded correctly, now the third path is incorrect, there is no util.js in the base dojo folder, I dont know why dojo would look there.
In order to solve the issue I tried describing the path better using the baseUrl property
<script>
dojoConfig = {
isDebug: true,
parseOnLoad: false,
baseUrl: './src/dojo-18/',
};
</script>
the dojo.js is referenced like this:
<script src="./src/dojo-18/dojo/dojo.js"></script>
Dojo does not look for util.js by itself, if it's doing that, you have imported a module called util by yourself, for example:
require([ "dojo/util" ], function(util) {
// This will not work because the util module does not exist
});
If you want to reference a self defined module, you have to configure the package first using dojoConfig:
<script>
dojoConfig = {
isDebug: true,
parseOnLoad: false,
baseUrl: './src/dojo-18/',
packages: [{
name: 'custom',
location: '/path/to/custom'
}]
};
</script>
Then you can reference a module in that package by using:
require([ "custom/util" ], function(util) {
// This will load the custom util module
});
In this case, the Dojo AMD loader will look for util.js inside the /path/to/custom folder, so it would become:
/path/to/custom/util.js

jQuery as AMD module and optimizing with r.js

Allright, he is the thing. I am using curl.js for my AMD loader, but i don't like much of "cram" because it needs to be run on unix and i am developing on Windows. So the r.js adapter for nodeJS from RequireJS library comes in mind, because node has already binary for Windows.
Now jQuery in current version (1.6.4) is not valid AMD module (coming in version 1.7) and there is dependencies in jQueryUI components, so i had to fake like this:
curl( [js!Core/jquery.js] )
.then( function() {
define('jquery', function() { return jQuery; });
})
My application is happy with this. However using r.js (version 0.26.0) fails on this part with following error:
Tracing dependencies for: boot
function (){return jQuery}
node.js:207
throw e; // process.nextTick error, or 'error' event on first tick
^
ReferenceError: jQuery is not defined
at eval at <anonymous> (r.js:7468:30)
at main (r.js:770:33)
at callDefMain (r.js:840:18)
This is my app.build.js
({
appDir: '../',
baseUrl: 'Scripts/',
paths: {
'link': '../../../Lib/#Javascript Libs/curl.js/src/curl/plugin/link.js'
},
dir: 'built',
optimize: 'none',
modules: [
{ name: 'boot' }
]
})
And here is complete boot.js for reference (coffeescript):
require([
'link!styles/main.css'
'js!Core/jquery.js!order'
'js!Core/underscore.js!order'
'js!Core/backbone.js!order'
]).then ->
define 'jquery', -> jQuery
.next(['Router/MainRouter'])
.then (MainRouter) ->
new MainRouter()
Backbone.history.navigate('home') unless Backbone.history.start(
pushState: false
)
Thank you in advance for any hint where the catch can be...
Correct. RequireJS uses a different syntax on its global requirejs() (aka require()) function. RequireJs also doesn't have the "js!" plugin built-in. You may have to include a path to it in your config. You could also use RequireJS's syntax for non-module javascript files.
Also: cram 0.2 will support Windows environments using Rhino. We're writing tests for cram 0.2 and will be releasing it shortly.
RequireJS syntax (remove js! prefix and include .js extension):
require([
'link!styles/main.css'
'order!Core/jquery.js'
'order!Core/underscore.js'
'order!Core/backbone.js'
], function (maincss, jQuery, underscore, backbone) {
// do something here
});

Dojo build -> dojo.require(); still needed?

this was my first dojo build so please excuse my ignorance in this matter.
I've just created my custom build from dojo build system using the following (very simplified) profile:
dependencies = {
stripConsole: "normal",
layers: [
{
name: "../dijits/cx/dijitsCXbuild.js",
copyrightFile: "CopyrightCX.txt",
dependencies: [
"dojo.parser",
"dijit.dijit",
"dijit._Widget",
"dijit._Templated",
"dijit._Container",
"dojo.i18n",
"dojo.NodeList-fx",
"dojox.grid.cells",
"dojox.grid.DataGrid",
"dojox.layout.GridContainer",
"dijit.TitlePane",
"dijits.cx.TaskPanel",
"dijits.cx.Identify"
]
}
],
prefixes: [
[ "dijit", "../dijit" ],
[ "dojox", "../dojox" ],
[ "dijits.cx", "../dijits/cx" ]
]
}
... well, it all proceeds fine and I get my own package with everything I requested. Then in my webapp I include the following
<script type="text/javascript">
djConfig = {
isDebug:false,
parseOnLoad:true,
locale:getLocale()
};
</script>
<script type="text/javascript" src="Lib/cxdojo/dojo/dojo.js"></script>
<script type="text/javascript" src="Lib/cxdojo/dijits/cx/dijitsCXbuild.js"></script>
... looks ok, until the code needs to instantiate the first dijit and it fails with the notorious : "dijits.cx. TaskPanel is not a constructor."
I can get rid of this problem by including the "dojo.require()" but that's something I though I'll get rid of by creating my custom own build. Any ideas of what am I doing wrong or what shall I do in order to avoid that 'dojo.require()' lines...
thanks heaps.
You still need the dojo.require in your file. The compressed build just prevents the dojo.require from doing a GET request for the file that is required by concatenating all the files into one file and shrinking it. This saves cycles on page load quite a bit (as I'm sure you have seen by now).
If you really want to get rid of the many dojo.require (which I'm not too crazy about because I like seeing what's used in the page), you can do something like this:
dojo.provide('my.main');
dojo.require('dijit.cx.TaskPane');
... all the other dojo.require statements ...
Then put this in a file in a directory parallel to dojo:
Lib/cxdojo/my/main.js
Lib/cxdojo/dojo/dojo.js
.. etc ...
Then change your dependencies to be:
dependencies: [
"my.main"
]
Then in your file, you can include it with the script tag:
<script type="text/javascript" src="Lib/cxdojo/my/main.js"></script>
Then, you only need one require:
dojo.require('my.main');
Another advantage of this approach is that you only need to change one file (the /my/main.js) when you add a module to your application.