I got an meteor app. On clientside I got a heavy calculation which freezes the whole tab in the browser while executing.
So I want to use Web Workers to avoid freezing and to handle the process better (terminating, loading informations percentages etc).
For getting the web workers to work I had to include a selfwritten webworker.js in my package.js.
So my main question is: How do I set up web workers in a meteor app (clientside)?
First I tried following things:
Add a file via api.addFile() with bare option.
Package.describe({
name: 'some:name',
version: '0.0.1',
// Brief, one-line summary of the package.
summary: 'Generates PDFs',
// URL to the Git repository containing the source code for this package.
git: '',
// By default, Meteor will default to using README.md for documentation.
// To avoid submitting documentation, set this field to null.
documentation: 'README.md'
});
Package.onUse(function(api) {
api.versionsFrom('1.1.0.2');
api.use(['mrt:redis#0.1.3'],
'server',
{weak: false, unordered: false}
);
api.addFiles([
"vendor/FileSaver.js",
"vendor/jspdf.debug.js",
"dcPDF.js"
],["client"]);
api.addFiles([
"server.js"
],["server"]);
api.addFiles(["pdfProgressWorker.js"],["client"], {bare: true});
api.export('DCPDF');
});
Meteor compresses all files in packages. To set up the workers right, I have to deploy the webworker.js as own js-file on clientside. The bare option seems not to work for this case. My js-files cannot call my webworker.js if I include the file in that way.
Second try:
I added my webworker.js to the /public folder.
Problem here: my webworker.js uses some external libaries which I already included in my own package. If I add the webworker.js to the public folder, I have to add all my external js-libaries too, which are all loaded on every site in my meteor app, which slows my whole application down. Not intended, not maintainable, not meteor-style (I think).
Related
I have been trying to build my gatsby (react) site recently using an external package.
The link to this package is "https://github.com/transitive-bullshit/react-particle-animation".
As I only have the option to change the props from the components detail, I cannot read/write the package file where it all gets together in the end as it is not included in the public folder of 'gatsby-build'.
What I have tried:
Editing the package file locally, which worked only on my machine but when I push it to netlify, which just receives the public folder and the corresponding package.json files and not the 'node-modules folder', I cannot make netlify read the file that I myself changed, as it requests it directly from the github page.
As a solution I found from a comment to this question, we can use the "Patch-Package" to save our fixes to the node module and then use it wherever we want.
This actually worked for me!
To explain how I fixed it: (As most of it is already written in the "Patch Package DOCS), so mentioning the main points:
I first made changes to my local package files that were giving the error.(For me they were in my node_modules folder)
Then I used the Patch Package Documentation to guide my self through the rest.
It worked after I pushed my changes to github such that now, Patch Package always gives me my edited version of the node_module.
When dealing with third-party modules that use window in Gatsby you need to add a null loader to its own webpack configuration to avoid the transpilation during the SSR (Server-Side Rendering). This is because gatsby develop occurs in the browser (where there is a window) while gatsby build occurs in the Node server where obviously there isn't a window or other global objects (because they are not even defined yet).
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
if (stage === "build-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /react-particle-animation/,
use: loaders.null(),
},
],
},
})
}
}
Keep in mind that the test value is a regular expression that will match a folder under node_modules so, ensure that the /react-particle-animation/ is the right name.
Using a patch-package may work but keep in mind that you are adding an extra package, another bundled file that could potentially affect the performance of the site. The proposed snippet is a built-in solution that is fired when you build your application.
I have read Google's documentation and a number of similar questions, and am not having any success adapting the answers to my issue. I am working with Google App Engine in a Node.js Standard Environment and already have much of my app working and correctly configured.
Now I am trying to use npm modules as library code for BOTH my server-side app, and a client-side javascript app I am serving as a static directory. For this example, consider the widely used jquery module, of course available in npm
I believe the issue is in my app.yaml file, distilled to the part relevant to this question:
handlers:
### THIS ROUTE IS NOT WORKING
- url: /client/shared/lib/jquery\.js$
static_files: node_modules/jquery/dist/jquery.js
upload: node_modules/jquery/dist/jquery\.js$
mime_type: text/javascript
### CLIENT-SIDE STATIC ROUTES ARE WORKING
- url: /client/shared
static_dir: shared
- url: /client.*$
static_dir: client
- url: /.*$
redirect_http_response_code: 301
script: auto
Of course, I have already run $ npm install jquery.
For example, from the "server-side" (my app.js file & friends), the following works perfectly:
import $ from "./node_modules/jquery/dist/jquery.js
Importing from my own "shared" code also works from both client and server via:
import { whatever } from "../shared/<module>.js"
But when I deploy and browse to https://<myapp>/client/shared/lib/jquery.js, I get a 404 error..
The goal is to be to get jquery from my "client-side" static javascript files with:
import $ from "../shared/lib/jquery.js"
(Or an equivalent relative path for deeper modules in the directory tree.)
Jquery is perhaps not the best example, if it bothers you pretend I'm talking about the "pluralize" library. I intend to use plenty of other npm distributions of js libraries and share them between my "client-side" statically served javascript files and my "server-side" code imported/pointed to from script: routes in app.yaml and/or imports from app.js
Also, I know I can use a "bundler" - or a cdn - etc. and I may eventually in production, but according to all the documentation this /should/ work. A correct answer will actually show me how to make this work and/or teach me what I don't understand about the static_files and upload handler options in app.yaml, not suggest an alternative that is a large edit distance away from my current setup.
Stack: Webpack 4.16.0, Node8, Vuejs2
I am seeing the below error, whilst serving my Vuejs application.
Error: Loading chunk 4 failed.
(missing: https://myapp.com/ui.chunk.bundle.js)
at HTMLScriptElement.s (demo:1)
This error is consistent across builds, the actual file itself is accesible via the URL.
I am using code splitting via import() and the initial app loads fine, but then the flow will break when another chunk is loaded, it can also vary between ui.chunk.bundle.js & vendors~ui.chunk.bundle.js.
When building for production, a new error is shown, but it seems related as also linked to loading modules:
demo:1 TypeError: Cannot read property 'call' of undefined
at o (demo:1)
at Object.349 (ui.chunk.bundle.js:1)
at o (demo:1)
at o.t (demo:1)
I have tried upgrading webpack and babel, but am at a loss as to what this could be down to as it was working perfectly fine before.
When running the application on my local machine and not Google App Engine, everything seems fine.
How the app is loaded:
It is loaded into other website via a script tag, so domainA.com runs the script tag which calls myapp.com/js and the flow begins, i.e the app loads various chunks based on some logic.
When accessing the webpack generated index page bundle at myapp.com everything loads correctly.
Please help!
That is rather deep and surely not easily fixed in two steps, best you create a new project using cli, if convenient with recommended presets, and if it still persist check the npm packages you installed and make sure none of them are discontinued and are up-to-date at least according to your version of vue.
Its might be due to "webpack.config.js" where you can just try with updating output object
module.exports = {
output: {
chunkFilename: '[id].chunk.[chunkhash].js',
}
};
Hope it should work!
This might be a cross site scripting problem.
Make sure that myapp.com sets the correct headers.
On myapp.com, set this header:
Access-Control-Allow-Origin: https://domainA.com
You should also make sure, that your script tag has async set to false:
<script async="false" …
I'm using MVC5/Durandal and wondering what the recommended approach to bundling/minifying a durandal application would be. Ive seen docs on using Weyland but will be deploying to an Azure Website and don't see how to leverage this in my .net-based deployment process. How can I go about configuring automated bundling/minification of my durandal application when deploying to Azure?
I've spent a bit of time trying to optimize an AngularJS application for one of the biggest banks in Holland. Although it's no Durandal, this might still give you some ideas.
So what did we use for bundling and minification? Out-of-the-box bundling and minifcation from ASP.NET MVC ( which is from the system.web.optimization namespace )
You need to get a couple of things in order to leverage this:
Organize your files
Organize your code files in a way that they can easily be bundled. We had a large tree structure under the /app folder in the web project. Something like:
- App
|- Modules
| |-Common
| | |- Directives
| | |- Templates
| | |- Filters
| --User
| ...
| app.js
So the application skeleton was inside the app.js and all the other JS files were required by the application. Point being: all SPA code is separated from vendor javscript files and the rest of course
Set up the budling inside the bundle configuration
That's a breeze now, just do regular-old-bundling from your Global.asax.cs:
Make sure there's a line in the Application_Start() with:
BundleConfig.RegisterBundles(BundleTable.Bundles);
That calls into your BundleConfig class which only needs 1 bundle to pack up the whole /app folder:
bundles.Add(new ScriptBundle("~/bundles/app")
.Include("~/app/*.js")
.IncludeDirectory("~/app", "*.js", true));
We needed the app.js to load first - therefore we put it explicitly at the top. Don't worry, it will not be requested twice.
For bundling - only the sequence of files can be important. However, through including that file explicitly, we could control that and it worked like a charm.
Minification
Now for minification we had to do some code changes. AngularJS can be used with different types of syntax - some of which can be minified, others give problems.
Example:
angular.module('myapp').controller(function($http,$scope) { ... });
can not be minified. The minifyer will change the name of $http so something shorter, after which the injector cannot do dependency injection anymore, since it only knows stuff called $http and $scope and not the minified variable name.
So for Angular you need to use a different syntax:
angular.module('myapp').controller(['$http', '$scope', function($http,$scope) { ... }]);
With this, the injector will know that the first argument of the function is '$http' because that's the first string variable in the array. OK, but that's Angular and you're looking for Durandal.
I've heard that Durandal uses AMD right? So within a module, minification shouldn't be a problem, because it should be smart enough. However, if you're using external things, you want to make sure everything still works. I've read here that you'll want to use te following syntax for your AMDs:
define("someModule", ["jquery", "ko"], function($,ko) { ... });
And that gave us a reduction of 80% of the requests and around the same number for the Javascript payload.
Added AngularJS bonus
This might not be of interest to you, but maybe for other readers. The reason we didn't get a 99% reduction of requests is because AngularJS uses something called 'directives'. These are like HTML templates. Those HTML templates still needed to be downloaded every time they were used.
They were also included in our /app folder - hence we had to add an IgnoreRoute in the routeconfig:
routes.IgnoreRoute("app/");
I Googled, but couldn't find anything similair for Durandal. So Angular will go and get all of the small HTML files, but will first check its $templatecache. In case the HTML content is not in the cache, it goes out and downloads it and places it in the cache, so it needs to be downloaded only once.
We, well I, wrote a T4 generator that outputs a JS file in which all the HTML files in the /app folder are added to the $templatecache. So the output would look like:
angular.module('myapp').run(function($templateCache) {
/// For all *.html files in the /app folder and its children
$templateCache.put('...filename...', '...content of html file ...');
});
Because this .JS file was inside the /app folder, it would immediately get bundled with the application, no more configuration required. This got our requests down for the whole application to just 1. Since the amount of HTML was quite small, it seemed to be faster to do 1 larger request, then multiple smaller ones.
Point is: if Durandal has something similair and it will look for some templates, find the caching mechanism ( because it will have it ) and try to tap into that.
Controlling bundling and minification
I'll quote this site: http://www.asp.net/mvc/overview/performance/bundling-and-minification
Bundling and minification is enabled or disabled by setting the value
of the debug attribute in the compilation Element in the Web.config
file. In the following XML, debug is set to true so bundling and
minification is disabled.
<system.web>
<compilation debug="true" />
</system.web>
So for your release build - this flag shouldn't be set and thus bundling + minification should happen.
But of course, you will want to test locally - you can either remove this from your web.config or override it with BundleTable.EnableOptimizations = true;
Deployment to Azure
Then you mention deployment to Azure. I don't know how this would be any different from deploying to a local server. We used web-deploy. Bundling and minification doesn't happen build-time, so there are no changes in the build process. Also, the optimization framework is being deployed with the site - so no difficult things for deployment either.
Maybe one thing though: you could consider adding the CDN for the libraries you are using:
bundles.Add(new ScriptBundle("~/bundles/jquery", "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js")
In case the CDN location of jQuery was already cached by the client's browser, you'll save another request.
Measuring the performance was easy: just open up the network tab on Chrome and reload the page ( make sure it's not caching ). Check the total number of requests and the total amount of data downloaded. Like I said: we saw a huge improvement.
Well, hope it helps or points you in a right direction.
The below answers are pretty complicated. I've just gone through this with a simple(r) approach here:
https://lifelibertycode.wordpress.com/2015/04/14/how-to-bundle-up-your-mvc-durandal-app/
The steps below:
Step 1: Install Node
Step 2: Install Gulp
$ npm install --global gulp
$ npm install --save-dev gulp
Step 3: Create your gulpfile.js
This should be at the root of your project, and should initially contain this:
var gulp = require('gulp');
gulp.task('default', function() {
// place code for your default task here
});
Step 4: Install gulp-durandal
npm install gulp-durandal --save-dev
Step 5: Update your gulpfile.js
var durandal = require('gulp-durandal');
gulp.task('durandal', function(){
durandal({
baseDir: 'app', //same as default, so not really required.
main: 'main.js', //same as default, so not really required.
output: 'main.js', //same as default, so not really required.
almond: true,
minify: true
})
.pipe(gulp.dest('dir/to/save/the/output'));
});
Step 6: Add a post-build event to your project
if '$(Configuration)'=='Release' (
cd $(ProjectDir)
gulp durandal
)
Step 7: Add a pre-build event to your project
I needed this because occasionally gulp would hang when generating the new main-built.js on top of an existing version. So I just delete the old version before the build begins:
if '$(Configuration)'=='Release' (
cd $(ProjectDir)/app
del main-built.js
del main-built.js.map
)
Now, when you build your project, you’ll generate a new main-built.js file each time that can be served down to your clients. Sweet.
At this point, you probably have some concerns.
How do I keep my files un-bundled when I’m debugging?
#if (HttpContext.Current.IsDebuggingEnabled) {
<script type="text/javascript" src="~/Scripts/require.js" data-main="/App/main"></script>
} else {
#Scripts.Render("~/Scripts/main-built")
}
Where ‘main-built’ is defined in your BundleConfig:
bundles.Add(new ScriptBundle("~/Scripts/main-built").Include(
"~/app/main-built.js"));
How do I bust cache when I have new stuff to ship?
If you’re using the above approach, bundling will take care of this for you. ASP.NET will detect a change to your main-built.js file and append a unique identifier to your bundles to bust the cache.
What if my client has downloaded my SPA, and then I ship an update. Won’t the (outdated) client-side code stick around until they refresh?
Yup. Unless you leverage build versioning to tell the client when it’s out of date, and then tell the user.
I happen have written a blog post about this:
https://javascriptkicks.com/articles/4230
Hopefully that helps you out
I want to have a strongloop example only using javascript without angular.
There's no complete working example without angular for now.
I want to simply include the browser.bundle.js in my index.html, then sync data from/to server side. In fact, I'm trying to replace pouchdb in my program since the couchdb seems not success in open source community.
I can't follow up this document correctly:
Running Loopback in the browser
create browser-app.js with the content from Running Loopback in the browser
copy past the content to browser-app.js
npm install loopback loopback-boot
browserify browser-app.js -o app.bundle.js Then I got error: Error: Cannot find module 'loopback-boot#instructions' from '/Users/simba/Projects/traveller-app/client/node_modules/loopback-boot'
There are few steps for this but its pretty simple.
Bootstrap your application via slc loopback.
Delete server/boot/root.js.
Uncomment two lines in server/server.js, it should look like:
...
// -- Mount static files here--
// All static middleware should be registered at the end, as all requests
// passing the static middleware are hitting the file system
// Example:
var path = require('path'); //this line is now uncommented
app.use(loopback.static(path.resolve(__dirname, '../client'))); //this line is now uncommented
...
Create index.html in the client dir (ie. client/index.html) with your contents.
That should get you a basic set up with just a basic front-end working. Let me know if you have any more issues.