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

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.

Related

Excluding JS scripts when building app with vite - is there a solution?

This question has been asked before but there appears to be no concrete answer. My situation is perhaps simpler, and perhaps someone has found a solution by now.
I'm using vite to build a vue.js app, and wish to exclude a bunch of .js files which are just data (word lists for a word game) and which will be modified over time by the server. The files are in a subdirectory of the main build. I have added them into index.html:
<body>
<script type="module" src="./src/assets/words/3letter.js"></script>
......
<script type="module" src="./src/assets/words/9letter.js"></script>
<div id="app" align="center">
</div>
<script type="module" src="/src/main.js"></script>
and after reading through several posts here and at github I have modified vite.config.js in various ways:
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url))
}
},
optimizeDeps: {
exclude: [
'./src/assets/words/*.js'
],
},
// build: {
// commonjsOptions: {
// exclude: [
// './src/assets/words/*.js'
// ]
// },
// }
})
but neither the optimizeDeps method or the commonjsOptions method works; when I run npm run build the word files are still included in the build, and the refs to them are removed from index.html
If I remove type="module" from the html refs, the build process gives me errors:
script src="./src/assets/words/3letter.js" in "/index.html" can't be bundled without type="module" attribute
and the relevant lines aren't removed from index.html, but the word lists are still being bundled! - they're easy to see inside the big resulting built .js file
I guess I was taking the wrong approach.
Since the .js files I want to excllde are just data (which my change over time)....
export const words4 = [
"ABED",
"ABET",
"ABLE",
"ABLY",
"ABUT",
"ACED",
....]
.....it's best that I recreate them as .json files instead of .js files, then use an http GET to retrieve them. Or, since MySql will be running on the server, store the words lists there.

Vue CLI v3 - How does it know what JS files should be chunked in a different file(s)

I am having hard times wrapping my mind around new CLI and configuration.
In the official documentation, I couldn't really find anything about CSS and how to add it as an entry point and not import it directly into an component or main.js file.
I realized that some JS files are being chunked into separate file, from main.js and the rest gets compiled where supposed to - into the app.js.
I was wondering, how does it know in the background what should be stored as "vendor" for the JS, but when I try to import some "vendor" SASS files into main.js it does not and it merges all within a single app.css file.
Can anyone tell me, how does one create/modify the vue.config.js and tell the bundler that I also want app.scss to be an entry point and vendor.scss to be another entry point.
I am unsure what are best practices for such purpose, but I always did it this way with my own webpack config...
Partial example below:
entry: {
vendor: [
'./styles/vendor.scss',
'./scripts/vendor.js'
],
app: [
'./styles/app.scss',
'./scripts/app.js'
]
}
EDIT #1
I think I got the first one...
"How does it know what should be chunked in "vendor" files?
Whatever gets imported from node_modules, it is being chunked.
What I did not figure out yet is... What if I am having my personal assets/styles/vendor directory where I #import those SASS files from NPM and do some modifications of variables or whatever.
Importing this file to main.js does not get chunked in this case... So there must be a way to tell bundler that I want everything within that directory or everything within vendor.scss file where everything is being imported, to be chunked out.
EDIT #2
I figured I can use WebPack's magical comments to import the main vendor SCSS file, such as:
import(/* webpackChunkName: "vendor" */ './assets/styles/vendor.scss')
I don't have a problem with this, but apparently the bundler does. It generates an empty vendor.[hash].js file as well.
EDIT #3
I did further research and learned that there's a command vue inspect which would output the webpack configuration.
So when making tweaks to vue.config.js, we can look a the output with this command if there's a bug or something is not working as expected.
Further more, I learned that if we specify entry directly in our vue.config.js file, that we will get an error that entry cannot be specified within our configuration file.
The following is forbidden to do so, but it's what I actually want to achieve...
// vue.config.js
module.exports = {
entry: {
app: [
'./src/main.js',
'./src/assets/styles/app.scss'
],
vendor: [
'./src/assets/styles/vendor.scss'
]
}
}
The actual proper way to do this will be an answer to my own question...
The way to achieve this is by using WebPack's Chain API.
However, if I did everything correctly, I still see a problem of generated vendor.[hash].js file with some WebPack module boilerplate. This JS file is also being injected to the index.html template.
Which leads to the same outcome as the attempt of my EDIT #2, except that we're no longer importing our Sass files within main.js
To modify entry points for my purpose of this question, we can do it the following way:
// vue.config.js
module.exports = {
chainWebpack: config => {
config
.entry('app')
.add('./src/assets/styles/app.scss')
.end()
.entry('vendor')
.add('./src/assets/styles/vendor.scss')
.end()
}
}
Note
We're not specifying the app entry JS file, which would be main.js by default, because we're not overriding the current entry point. Instead, we're extending it, so everything works as expected.
UPDATE
Until WebPack resolves this in future major releases, I found a great package - fqborges/webpack-fix-style-only-entries. It solves this issue that I was having and I'd suggest you to use it.
Final configuration would look like this:
const FixStyleOnlyEntries = require('webpack-fix-style-only-entries')
module.exports = {
chainWebpack: config => {
config
.entry('app')
.add('./src/assets/styles/app.scss')
.end()
.entry('vendor')
.add('./src/assets/styles/vendor.scss')
.end()
},
configureWebpack: {
plugins: [
new FixStyleOnlyEntries()
]
}
}
UPDATE #2
After further investigation and use of such configuration for projects, I realized that I had to use !important in styles where I had a need to override anything vendor related.
This is simply because WebPack will inject app, before vendor (both JS and CSS) and it will cause such issue.
Even if we modify the configuration from above and move app entry, below the vendor entry, it will still fail. Reason being, because we're modifying the entry point which already exists by default within vue-cli config. We're adding more entries to the app and we're adding new vendor entry.
To fix this issue of ordering, we must delete the app entirely and then create it ourselves.
const FixStyleOnlyEntries = require('webpack-fix-style-only-entries')
module.exports = {
chainWebpack: config => {
config.entryPoints.delete('app')
config
.entry('vendor')
.add('./src/assets/styles/vendor.scss')
.end()
.entry('app')
.add('./src/main.js')
.add('./src/assets/styles/app.scss')
.end()
},
configureWebpack: {
plugins: [
new FixStyleOnlyEntries()
]
}
}

Wallaby with Browserify and TypeScript modules

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'
]

How can I optimize this custom dojo 1.7.2 build

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)

Make a build in dojo 1.7.2

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>