This is my distillation of a build failure I was getting. The symptom was that when optimizing with shrinksafe my build would fail with the error:
[exec] js: "<eval'ed string>#1(Function)#1(eval)", line 127: uncaught JavaScript runtime exception: TypeError: Cannot read property "1" from null
[exec] at <eval'ed string>#1(Function)#1(eval):127
[exec] at <eval'ed string>#1(Function)#1(eval):163
If my code pulled in its nls files with a pattern such as
"dojo/i18n!./nls/MyResource"
However, this construct is common throughout much dojo code, which builds cleanly. So I experimented by copying some dojo code into my module and discovered that if the nls resource was loaded into the dojo/dojo layer then my layers built correctly, if I loaded the same nls resource in my own layer then we get the failure above.
So cutting this right down to a minimal case, I copied dijit/form/_ComboBoxMenuMixin.js to my own module and also the corresponding nls resources.
I have three test cases, one works, the other two give the failure above.
My questions:
Seems like I need to include my own nls resources in the "dojo/dojo" layer, it must be precisely this layer. Surely this can't be right? What are my alternatives?
Working profile:
layers: {
"dojo/dojo" : {
customBase: false,
include: [
"modules/nls/ComboBox",
],
exclude: []
},
"MyLayer" : {
customBase: false,
include: [
"modules/ComboCopy",
],
exclude: []
},
}
Failure: nls in same layer
layers: {
"dojo/dojo" : {
customBase: false,
include: [
],
exclude: []
},
"MyLayer" : {
customBase: false,
include: [
"modules/nls/ComboBox",
"modules/ComboCopy",
],
exclude: []
},
}
failure, load nls in a different layer name
layers: {
"myNlsLayer" : {
customBase: false,
include: [
"modules/nls/ComboBox",
],
exclude: []
},
"MyLayer" : {
customBase: false,
include: [
"modules/ComboCopy",
],
exclude: []
},
NLS modules shouldn’t be specified as being included in layers. When your layer modules are processed, all of their NLS dependencies will be automatically bundled into related layers with a filename suffix corresponding to each possible locale. e.g. for a layer MyLayer.js you will also get a MyLayer_en-us.js, MyLayer_es-es.js, etc. This enables visitors to load only the language bundle they need.
If you want to forcibly include a particular locale within your layers (for example, because you know all your visitors only speak English), you can use the includeLocales property to do so:
layers: {
MyLayer: {
includeLocales: [ 'en-us' ]
}
}
Whilst your first profile may appear to work, it is unlikely that it is actually doing what you expect, which is probably why ShrinkSafe is crashing.
A couple other notes:
ShrinkSafe is deprecated; you should really use Closure Compiler or UglifyJS instead.
The customBase flag applies only to the main dojo/dojo layer and means “do not automatically include the default Dojo Base modules”. You do not need to apply it to your other layers.
Related
This is probably a pretty esoteric and specific issue to my workflow, so I don't know if anyone else has come across it in the past. I use an aws-cloud9 workspace to do development for my Vue application. I recently started using dynamic imports in my vue-router file to split up chunks and reduce initial file load size. In terms of the webpack compiler and running in the browser, it works great! However, cloud9's linter (which I believe is using eslint) is failing as soon as it gets to my first dynamic import with the error 'Parsing error: Unexpected token import'. I have a .eslintrc.js file in the directory of my project which looks like this:
// https://eslint.org/docs/user-guide/configuring
module.exports = {
root: true,
parser: "vue-eslint-parser",
parserOptions: {
parser: 'babel-eslint',
ecmaVersion: 2018,
'allowImportExportEverywhere': true
},
env: {
browser: true
},
extends: [
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
'plugin:vue/essential',
// https://github.com/standard/standard/blob/master/docs/RULES-en.md
'standard'
],
// required to lint *.vue files
plugins: [
'vue',
'babel'
],
// add your custom rules here
rules: {
// allow async-await
'generator-star-spacing': 'off',
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'space-before-function-paren': 0,
'semi': [1, 'always'],
'quotes': 0,
'no-tabs': 0,
'allowImportExportEverywhere': true,
'no-mixed-spaces-and-tabs': 0
}
};
Other issues have mentioned edits to the eslintrc file to fix the issue. Changing the eslintrc file in my project changes what errors show up at compile time, but the aws-cloud9 ide is still presenting the error in the gutter.
I am trying to get Wallaby to work with a TypeScript app, using Browserify and Wallabify. However, when I run Wallaby, it outputs No failing tests, 0 passing, and all test indicators are grey.
The file app/spec.setup.ts is responsible for loading node modules dependencies such as chai, sinon, and the app's main module. app/spec.util.ts provides some helpers, imported by individual spec files.
module.exports = function() {
var wallabify = require('wallabify');
var wallabyPostprocessor = wallabify({
entryPatterns: [
'app/spec.setup.ts',
'app/src/**/*.spec.ts'
]
}
);
return {
files: [
{pattern: 'app/spec.setup.ts', load: false, instrument: false},
{pattern: 'app/spec.util.ts', load: false, instrument: false},
{pattern: 'app/src/**/*.ts', load: false},
{pattern: 'app/src/**/*.spec.ts', ignore: true}
],
tests: [
{pattern: 'app/src/**/*.spec.ts', load: false}
],
testFramework: 'mocha',
postprocessor: wallabyPostprocessor,
bootstrap: function (w) {
// outputs test file names, with .ts extensions changed to .js
console.log(w.tests);
window.__moduleBundler.loadTests();
}
};
};
What's interesting is that I don't get any feedback from changing entryPatterns, even setting it to an empty array or invalid file names. The result is still the same. Only if I remove it entirely, I get errors such as Can't find variable: sinon.
I've also figured that the entryPatterns list may need the compiled file names, i.e. .js instead of .ts extension. However, when I do that, I get Postprocessor run failure: 'import' and 'export' may appear only with 'sourceType: module' on spec.setup.ts.
I don't know what is the correct way to configure Wallabify for TypeScript compilation, and I couldn't find any complete examples on the web, so I'd appreciate any hints.
P.S. with my current StackOverflow reputation I couldn't add two new tags: wallaby and wallabify. Could someone do me a favour and add the two tags please.
Because TypeScript compiler renames files to .js and applied before wallabify, you need to change your entry patterns like this to make it work:
entryPatterns: [
'app/spec.setup.js',
'app/src/**/*.spec.js'
]
I'm trying to get Durandal.js optimizer working on my test project, but it seems to generate nothing to main-built.js. I use the following command from node.js command prompt, in durandal/amd folder:
optimizer.exe --verbose true
Result is
Using default base configuration.
Configuring for deploy with almond (custom).
{
"name": "durandal/amd/almond-custom",
"inlineText": true,
"stubModules": [
"durandal/amd/text"
],
"paths": {
"text": "durandal/amd/text"
},
"baseUrl": "C:\\Users\\Tommi Gustafsson\\Documents\\Visual Studio 2012\\Projects\\DurandalTests\\DurandalTest1\\TestApp",
"mainConfigFile": "C:\\Users\\Tommi Gustafsson\\Documents\\Visual Studio 2012\\Projects\\DurandalTests\\DurandalTest1\\TestApp\\main.js",
"include": [
"main-built",
"main",
"bindings/tinymce-binding",
"durandal/app",
"durandal/composition",
"durandal/events",
"durandal/http",
"text!durandal/messageBox.html",
"durandal/messageBox",
"durandal/modalDialog",
"durandal/system",
"durandal/viewEngine",
"durandal/viewLocator",
"durandal/viewModel",
"durandal/viewModelBinder",
"durandal/widget",
"durandal/plugins/router",
"durandal/transitions/entrance",
"raphael-amd/eve.0.3.4",
"raphael-amd/raphael.2.1.0.amd",
"raphael-amd/raphael.2.1.0.core",
"raphael-amd/raphael.2.1.0.svg",
"raphael-amd/raphael.2.1.0.vml",
"viewmodels/flickr",
"viewmodels/modal1",
"viewmodels/myPage",
"viewmodels/shell",
"viewmodels/welcome",
"text!views/detail.html",
"text!views/flickr.html",
"text!views/modal1.html",
"text!views/myPage.html",
"text!views/shell.html",
"text!views/welcome.html"
],
"exclude": [],
"keepBuildDir": true,
"optimize": "uglify2",
"out": "C:\\Users\\Tommi Gustafsson\\Documents\\Visual Studio 2012\\Projects\\DurandalTests\\DurandalTest1\\TestApp\\main-built.js",
"pragmas": {
"build": true
},
"wrap": true,
"insertRequire": [
"main"
]
}
Deleting old output file.
Tracing dependencies for: durandal/amd/almond-custom
Then, when I check main-built.js, it is empty. Can anyone help me what is the problem? I have several AMD modules in the test project, including Raphael.js AMD modules.
My requirejs configuration looks like this:
requirejs.config({
paths: {
'text': 'durandal/amd/text',
'eve': './raphael-amd/eve.0.3.4',
'raphael.core': './raphael-amd/raphael.2.1.0.core',
'raphael.svg': './raphael-amd/raphael.2.1.0.svg',
'raphael.vml': './raphael-amd/raphael.2.1.0.vml',
'raphael': './raphael-amd/raphael.2.1.0.amd',
'tinymce': "../Scripts/tinymce/jquery.tinymce.min"
}
});
In the same amd folder, where optimizer is stored, try running node r.js -o app.build.js. I've seen r.js sometimes choke about some dependencies, which resolves without problem when loading via require.js. For whatever reason the error messages won't show up when using optimizer --verbose. Typically the error message provides enough information to see where this occurs and if you've to update require.contig.paths or a specific define dependency.
I am working on my first project which uses a dojo 1.7.2 component, and only need a vertical slider widget. I was able to create a custom build which is supposed to include only the modules needed for my stated dependencies. Using the following build profile, and the command C:\dojo-release-1.7.2-src\util\buildscripts>build -p profiles/km.admin.dashboard.profile.js -r the resulting release/dojo/dojo.js.uncompressed.js is 796kb, and the release/dojo/dojo.js is 236kb. Is there any way to exclude more unneeded modules to reduce the file size? For instance, I just opened the release/dojo/dojo.js.uncompressed.js and took a quick look, there is a dojo/json package, I am not using any json. How do I exclude it? Thank you.
dependencies = {
layers: [
{
name: 'dojo.js',
customBase: true,
dependencies: [
'dojo/dojo',
'dojo.aspect',
'dojo/selector/acme',
'dojo/cldr/nls/number',
'dijit.form.VerticalSlider',
'dijit.form.VerticalRule',
'dijit.form.VerticalRuleLabels'
]
}
],
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
},
prefixes: [
[ 'dijit', '../dijit' ],
[ 'dojox', '../dojox' ]
]
}
There are some approaches by which you can trim down dojo.js to a bare minimum and keep adding the modules within dojo.js that you really need.
See:
http://dojotoolkit.org/reference-guide/1.7/build/customBase.html
and also:
http://www.sitepen.com/blog/2008/07/01/dojo-in-6k/ (this is somewhat old and cutombase approach in the first link might work better)
Well, I read all about build and all about dojo. Three days nightmare and so on... Need some help.
I'm using the last version of dojo. 1.7.2 in:
</sites/somesite/scripts/dojo17>
which contains
--dojo
--dijit
--dojox
--utils
I use the following profile:
dependencies = {
stripConsole: "all",
action: "release",
optimize: "shrinksafe",
layerOptimize: "shrinksafe",
//optimize: "closure",
//layerOptimize: "closure",
//mini: true,
//localeList : 'en-us',
//cssOptimize: "comments",
//selectorEngine: "acme",
releaseName: "content7",
layers: [
{
// This is a specially named layer, literally 'dojo.js'
// adding dependencies to this layer will include the modules
// in addition to the standard dojo.js base APIs.
name: "dojo.js",
customBase : true,
dependencies: [
"dojo.fx",
"dijit.form.Button",
"dojox.gauges.AnalogGauge",
"dojox.gauges.AnalogArcIndicator",
"dojox.gauges.AnalogNeedleIndicator",
"myApp.smartmix"
]
}
],
prefixes: [
[ "dijit", "../dijit" ],
[ "dojox", "../dojox" ],
[ "myApp", "../../../myApp" ]
]
};
then i use this build script
./build.sh profile=../../../../myApp/myApp.profile.js releaseDir=../../../release
And I got the
</sites/somesite/scripts/release/content7>
which contains
--dijit
--dojo
--dojox
--myApp
NOW in my index.html file I have
<script type="text/javascript">
//<![CDATA[
var djConfig = {
parseOnLoad: true,
isDebug: false,
modulePaths: {
'myApp': '../myApp'
}
};
//]]>
</script>
<script type="text/javascript" src="scripts/release/content7/dojo/dojo.js"></script>
<script>
dojo.require('myApp.smartmix');
</script>
And YES this reduce the 230 files loaded without the build to 153 files.
BUT stills I (want to) believe that is posibble to reduce to one or 2 files.
But HOW?????
Please, some help will be appreciated!!!!
Ok, your profile is not right.
1st of all: You are using customBase, which is an advanced property for creating a minimal version of dojo core. I don't think you want that, do you? Normally, you just let dojo build its core normally, and that ends up as dojo.js in your output dir.
2nd of all: Every layer entry there will generate a minified .js file with all the files in dependencies inside it.
So, if you want your myApp stuff in a built JS file, you'll need to create a layer, and put your files in its dependencies.
Dojo will still generate all the individual files - but you don't have to deploy them. Just deploy the layer files. I usually have a layer for Dojo core, a layer for the dijit/dojox stuff I want, and then a layer for my custom JS. Then there are three JS files, which dojo will output in the dojo dir, and they are used in the HTML page.
...
layers: [
{
// this is a layer 'application', which will cache all
// dependencies to smartmix and declare smartmix in the same file
name: "../../../myApp/smartmix.js",
dependencies: [
"dojo.fx",
"dijit.form.Button",
"dojox.gauges.AnalogGauge",
"dojox.gauges.AnalogArcIndicator",
"dojox.gauges.AnalogNeedleIndicator",
"myApp.smartmix"
]
}
],
...
you will need only two requests;
<script src=..dojo.js></script>
and
<script>require(["myApp.smartmix"], function(smartmixApplication) { });</script>