I would like perform some size optimization on generated files by qooxdoo. 800Ko is quite huge... For information, it is based on a desktop approach.
I'm using this configuration :
"OPTIMIZE" : ["basecalls", "comments", "privates", "strings", "variables", "variants", "whitespace"]
Without success...
Any idea ?
Client optimisation
It's the easy way. Set up gzip compression in your web-server. It'll make your build ~ 200-300 kB. You can even pre-compress your build and serve app.js.gz directly.
Then set up your web-server cache. On way is to configure reasonable cache expiration time, e.g. a week or a month. For more aggressive caching, expiration is set to forever (years) and your build URL looks like /static/app.js?v=123. You can use simple incrementing number, VCS revision or file hash.
Partial build
Harder but more flexible way is to use parts and combine it with client optimisation described above. This way you can build your application in the way that it loads its components on-demand and won't require loading everything upfront. This however requires changing your application, making in more modular and less coupled, which is generally something good though.
In your config.json you need to define parts, the components of your application that usually correspond to different functionality. I usually extent common job like this:
"common" :
{
"packages" :
{
"sizes" :
{
"min-package" : 64,
"min-package-unshared" : 16
},
"additional-merge-constraints" : true,
"parts" :
{
"boot" :
{
"include" : ["${QXTHEME}", "${APPLICATION}.Application"]
},
"functionality1" :
{
"include" : ["${APPLICATION}.controller.Functionality1"]
},
"functionality2" :
{
"include" : ["${APPLICATION}.controller.Functionality2"]
},
...
}
}
}
Boot part here contains minimal Qooxdoo dependencies required for bootstrapping the application. Note that unlikely your boot part will be less than 500 kB (uncompressed).
Then when you want to use some functionality you do:
qx.io.PartLoader.require(['functionality1'], function()
{
new (qx.Class.getByName('app.controller.Functionality1')).doSomething();
}, this);
Note that the part loader resolves dependencies for you, as part functionality1 may have its dependencies. In fact, partial build with 3 defined parts above may lead to less or more than 3 files in result. The generator uses sophisticated dependency management so it can split and collapse parts if it benefits the load performance.
The optimization config you are using is the default one. So you should already get an optimized build, when you run ./generate.py build. Look into build/script/{myNamespace}.js. The first part of the script (the managing or loading code so to speak) isn't optimized, but the framework code and your app code is optimized (one long line at the end, which is minified etc.).
The manual has more details:
How to configure the optimizations?
Which optimization does what?
Related
I have a simple vue / nuxt project that I would like to serve from AWS lambda.
For this, I'd like to group everything into a single file.
I see that Nuxt is splitting the files in order to only load what matters at a given time, but the app is a single page, is for internal use and loading time / memory usage is completely irrelevant.
My question is 2 fold:
how can I disable the file splitting
is there a way to pack everything into a single index.html file? I didn't find a solution on the web because the moment I start to research solutions, I keep finding posts about SSR which is also totally irrelevant to my case.
For the split part, this one with all set to false should be enough: https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-build#splitchunks
Like this
export default {
build: {
splitChunks: {
layouts: false,
pages: false,
commons: false
}
}
}
This one should also help: https://github.com/nuxt/nuxt.js/issues/2363
You also can have the whole control of the webpack config here: https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-build#optimization
As for hosting on Lambda, you can check those 2 articles:
https://www.serverless.com/examples/aws-node-vue-nuxt-ssr
https://medium.com/#fernalvarez/serverless-side-rendering-with-aws-lambda-nuxtjs-b94d15782af5
I'm using React 17 with cra-template-pwa to create a PWA. One of my UI libraries has several hundred static image resources that all get preloaded in the PWA (and I don't use most of them). This causes a long delay in enabling the PWA, and even causes Lighthouse to crash. I'm looking at various approaches to fixing the problem, but for a quick fix just to run lighthouse, I'd like to just disable precaching. I haven't been able to find concrete info how to do this. Any advice?
The cleanest solution would entail using the exclude option in the workbox-webpack-plugin configuration, but that requires ejecting in create-react-app.
Something you can do without ejecting, though, is to explicitly filter out entries from the injected self.__WB_MANIFEST array before passing the value to precacheAndRoute().
Your service-worker.js could look something like:
import {precacheAndRoute} from 'workbox-precaching';
// self.__WB_MANIFEST will be replaced with an
// Array<{url: string, revision: string}> during the build process.
// This will filter out all manifest entries with URLs ending in .jpg
// Adjust the criteria as needed.
const filteredManifest = self.__WB_MANIFEST.filter((entry) => {
return !entry.url.endsWith('.jpg');
});
precacheAndRoute(filteredManifest);
The downsides of this approach is that your service-worker.js file will be a bit larger than necessary (since it will include inline {url, revision} entries that aren't needed), and that you'll end up triggering the service worker update flow more than strictly necessary, if the contents of one of your images changes. Those unnecessary service worker updates won't actually harm anything or change the behavior of your web app, though.
Background:
I'm building an SPA (Single Page Application) PWA (Progressive Web App) using Vue.js. I've a remote PostgreSQL database, serving the tables over HTTP with PostgREST. I've a working Workbox Service Worker and IndexedDB, which hold a local copy of the database tables. I've also registered some routes in my service-worker.js; everything is fine this far....
I'm letting Workbox cache GET calls that return tables from the REST service. For example:
https://www.example.com/api/customers will return a json object of the customers.
workbox.routing.registerRoute('https://www.example.com/api/customers', workbox.strategies.staleWhileRevalidate())
At this point, I need Workbox to do the stale-while-revalidate pattern, but to:
Not use a cache, but instead return the local version of this table, which I have stored in IndexedDB. (the cache part)
Make the REST call, and update the local version, if it has changed. (the network part)
I'm almost certain that there is no configurable option for this in this workbox strategy. So I would write the code for this, which should be fairly simple. The retrieval of the cache is simply to return the contents of the requested table from IndexedDB. For the update part, I'm thinking to add a data revision number to compare against. And thus decide if I need to update the local database.
Anyway, we're now zooming in on the actual question:
Question:
Is this actually a good way to use Workbox Routes/Caching, or am I now misusing the technology because I use IndexedDB as the cache?
and
How can I make my own version of the StaleWhileRevalidate strategy? I would be happy to understand how to simply make a copy of the existing Workbox version and be able to import it and use it in my Vue.js Service Worker. From there I can make my own necessary code changes.
To make this question a bit easier to answer, these are the underlying subquestions:
First of all, the StaleWhileRevalidate.ts (see link below) is a .ts (TypeScript?) file. Can (should) I simply import this as a module? I propably can. but then I get errors:
When I to import my custom CustomStaleWhileRevalidate.ts in my main.js, I get errors on all of the current import statements because (of course) the workbox-core/_private/ directory doesn't exist.
How to approach this?
This is the current implementation on Github:
https://github.com/GoogleChrome/workbox/blob/master/packages/workbox-strategies/src/StaleWhileRevalidate.ts
I don't think using the built-in StaleWhileRevalidate strategy is the right approach here. It might be possible to do what you're describing using StaleWhileRevalidate along with a number of custom plugin callbacks to override the default behavior... but honestly, you'd end up changing so much via plugins that starting from scratch would make more sense.
What I'd recommend that you do instead is to write a custom handlerCallback function that implements exactly the logic you want, and returns a Response.
// Your full logic goes here.
async function myCustomHandler({event, request}) {
event.waitUntil((() => {
const idbStuff = ...;
const networkResponse = await fetch(...);
// Some IDB operation go here.
return finalResponse;
})());
}
workbox.routing.registerRoute(
'https://www.example.com/api/customers',
myCustomHandler
);
You could do this without Workbox as well, but if you're using Workbox to handle some of your unrelated caching needs, it's probably easiest to also register this logic via a Workbox route.
I just found out about Speedment, a Java 8 Stream-based OR/M library, and have to say that I love the idea of it. No more crazy configurations or spending time sifting through 900 pages of Hibernation docs to find the right way to annotate my classes: Speedment just reads your database, generates Java classes for you and gives you a stream-based API to run DDL statements against them. Wicked cool.
However, the one big deal breaker is that it seems like you have to use the Speedment UI for configuring your DB connection. Furthermore, the docs don't seem to specify how you can do things like:
Specify which tables you want code generated against (maybe there's a few tables inside a database that you don't want models generated for
Execute stored procedures
Configure in-memory caches
etc. Looking on GitHub I can't seem to find how the code is wired together from the UI to produce a configuration object. Just wondering if there's a way to configure Speedment sans UI (perhaps via JSON or YAML), and if so, what configurations are available.
It is possible to configure Speedment without the UI, but it requires some tinkering. Basically, to generate code from a database, you need to manually create a speedment.json-file and specify which schema to generate from manually.
Create a new Maven Project (a pom.xml-file and a src/main/java-directory).
Create a file /src/main/json/speedment.json
Enter the following:
{
"config" : {
"name" : "yourproject",
"packageName" : "com.yourcompany",
"packageLocation" : "src/main/java/",
"dbmses" : [{
"name" : "db0",
"typeName" : "MySQL",
"ipAddress" : "127.0.0.1",
"port" : 3306,
"schemas" : [{
"name" : "your_db_schema"
}]
}]
}
}
Run the Maven goal: mvn speedment:reload -Ddbms.username=root -Dbms.password=password (with the credentials for your database)
Finally, run the Maven goal: mvn speedment:generate
The first goal connects to the database and fills in any missing configuration details in the .json file. The second goal generates .java-code.
To disable a specific table, set the json-property "enabled" to false. Youc an also disable individual columns this way.
If you want, you can now configure the generation directly in the .json-file and then regenerate.
This weekend i tryed to test a package "A" from my meteor app.
This package depends on another package "B" that defines all collections. So the package "B" expose all required collections.
The package "A" expose a main object that have some methods that use the collections exposed in "B".
I want to replace some collections by a code like this :
myCol = {
"findOne": return {_id: 1, "name": ben}
}
But it fails. This code is ok from tinytest.add code, but in the methods of the package "A", it still uses the original Collection variables. I've seen in the build folder that everything is re-written by the build system, so i wonder what is the best way to test my code without depending on those Collection variables.
I have some ideas like storing those variables in a main object that has get/set methods. It might allow me to change everything when i do test.
Thanks for help
Here is the sample app : https://github.com/MeteorLyon/tutorial-package-dependancy-testing
Follow the README.md to run different test.
If you find a solution it's great.
If you are looking for stubs, I'd highly recommend using sinon. Specifically, have a look at the stubs and the sandbox portions of the docs. You can find atmosphere packages here. Here's a quick example:
Tinytest.add('my test', sinon.test(function(test) {
// this is sandboxed stub - we are writing to a global object
// but it will be restored at the end of the test
test.stub(Meteor, 'userId', function() {
return USER_ID;
});
// let's do the same thing with a collection
test.stub(Posts, 'findOne', function() {
return {_id: 1, name: 'ben'};
});
var post = Posts.findOne();
test.equal(post.name, 'ben');
}));
Keep in mind that tinytest is an integration test framework, so you may get better tests by fully utilizing both package's APIs. With respect to testing collection interactions, we've found its better to not stub very much and just insert and cleanup as needed. But that's pretty general advice - there may be some specific reason why this can't work in your particular use case.