Flutter Web Github Pages is too lazy and i don't know why - html

i'm trying to deploy a flutter web app to GitHub Pages.
First of all, i was getting the same problem as this, and their solution worked for me too.
This means that i add the <base href='/web'> to my index.html
But now, when i'm lauching my url from GitHub Pages, the site is loading too lazily, what i think isn't the correct behavior. Like you can see in the image below:
Is there a way to lauch the site faster? What should i do?

In general, website loading times are related to the bundle size. Flutter web apps tends to have large bundles, so the load times will inevitably be longer than websites built with other technologies.

So, i was searching and a friend observed that the serviceWorker, in the index.html file, was the problem. Now my app runs as fast as it shoud be.
Apparently, that function was trying to execute something and failed (but this failure cost 4 seconds, stipulated in code). So i commented this all and added a loadMainDartJs() call in the start, as you can see below:
loadMainDartJs();
<!-- if ('serviceWorker' in navigator) {-->
<!-- // Service workers are supported. Use them.-->
<!-- window.addEventListener('load', function () {-->
<!-- // Wait for registration to finish before dropping the <script> tag.-->
<!-- // Otherwise, the browser will load the script multiple times,-->
<!-- // potentially different versions.-->
<!-- var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;-->
<!-- navigator.serviceWorker.register(serviceWorkerUrl)-->
<!-- .then((reg) => {-->
<!-- function waitForActivation(serviceWorker) {-->
<!-- serviceWorker.addEventListener('statechange', () => {-->
<!-- if (serviceWorker.state == 'activated') {-->
<!-- console.log('Installed new service worker.');-->
<!-- loadMainDartJs();-->
<!-- }-->
<!-- });-->
<!-- }-->
<!-- if (!reg.active && (reg.installing || reg.waiting)) {-->
<!-- // No active web worker and we have installed or are installing-->
<!-- // one for the first time. Simply wait for it to activate.-->
<!-- waitForActivation(reg.installing ?? reg.waiting);-->
<!-- } else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {-->
<!-- // When the app updates the serviceWorkerVersion changes, so we-->
<!-- // need to ask the service worker to update.-->
<!-- console.log('New service worker available.');-->
<!-- reg.update();-->
<!-- waitForActivation(reg.installing);-->
<!-- } else {-->
<!-- // Existing service worker is still good.-->
<!-- console.log('Loading app from service worker.');-->
<!-- loadMainDartJs();-->
<!-- }-->
<!-- });-->
<!-- // If service worker doesn't succeed in a reasonable amount of time,-->
<!-- // fallback to plaint <script> tag.-->
<!-- setTimeout(() => {-->
<!-- if (!scriptLoaded) {-->
<!-- console.warn(-->
<!-- 'Failed to load app from service worker. Falling back to plain <script> tag.',-->
<!-- );-->
<!-- loadMainDartJs();-->
<!-- }-->
<!-- }, 4000);-->
<!-- });-->
<!-- } else {-->
<!-- // Service workers not supported. Just drop the <script> tag.-->
<!-- loadMainDartJs();-->
<!-- }-->
At the moment i don't need serviceWork, and this suits weel for me.

Related

Forwarded URL renders the webpage in half the height as normal for a Flutter Web app hosted in Firebase

I have a firebase hosted Flutter Web application which is a game. Since the URL for the Firebase hosted site (https://jw-daily.web.app) is difficult to remember for users, I bought a domain name (joinedwords.com) and redirected the URL to the firebase hosted site.
Problem is that when I type the domain URL i.e. joinedwords.com, the website renders in only half the height like below:
However, if I type the original URL (https://jw-daily.web.app) in the browser, the webpage renders in full like below:
All that I have done is with my domain provider, I have set a forward with masking of joinedwords.com => https://jw-daily.web.app/
I looked up all the other solutions around why a webpage is rendering in half. However most of them are asking to make changes to the code and I don't want to do that since the original URL is working fine. Incidentally this issue is happening only on mobile browsers and not happening on desktop. In desktop, the website renders correctly regardless of which URL is typed.
Please suggest if you are aware of how we can solve this problem. Here is my index.html file.
<!DOCTYPE html>
<html prefix="og: http://ogp.me/ns#">
<head>
<!--
If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from.
The path provided below has to start and end with a slash "/" in order for
it to work correctly.
For more details:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
-->
<base href="/">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A Daily Word Game">
<meta image="" />
<meta property="og:image:url" content="https://s3.us-east-2.amazonaws.com/joint.words/joined-xxx.png"
property="og:image:secure_url" content="https://s3.us-east-2.amazonaws.com/joint.words/joined-xxx.png"
property ="og:image:alt" content="Joined Words Logo"
property="og:image:type" content="image/png"
/>
<!--
property="og:image:width" content="100"
property="og:image:height" content="100"
-->
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Joined Words">
<link rel="apple-touch-icon" href="https://s3.us-east-2.amazonaws.com/joint.words/joined-256.png">
<!-- Favicon -->
<link rel="shortcut icon" href="favicon.png" type="image/x-icon">
<link rel="icon" href="favicon.png" type="image/x-icon">
<title>Joined Words</title>
<link rel="manifest" href="manifest.json">
<meta name="google-site-verification" content="XXXXXXXXX-XXXXXX" />
/>
<!-- Global site tag (gtag.js) - Google Ads: xxxxxxxxx -->
<script async src="https://www.googletagmanager.com/gtag/js?id=AW-xxxxxxxxxxx"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'AW-xxxxxxxxxxx');
</script>
<!-- Event snippet for Website traffic conversion page -->
<script>
gtag('event', 'conversion', {'send_to': 'xxxxxxxxxxxxxxxxxxx'});
</script>
</head>
<body>
<!-- This script installs service_worker.js to provide PWA functionality to
application. For more information, see:
https://developers.google.com/web/fundamentals/primers/service-workers -->
<script>
var serviceWorkerVersion = null;
var scriptLoaded = false;
function loadMainDartJs() {
if (scriptLoaded) {
return;
}
scriptLoaded = true;
var scriptTag = document.createElement('script');
scriptTag.src = 'main.dart.js?version=1';
scriptTag.type = 'application/javascript';
document.body.append(scriptTag);
}
if ('serviceWorker' in navigator) {
// Service workers are supported. Use them.
window.addEventListener('load', function () {
// Wait for registration to finish before dropping the <script> tag.
// Otherwise, the browser will load the script multiple times,
// potentially different versions.
var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;
navigator.serviceWorker.register(serviceWorkerUrl)
.then((reg) => {
function waitForActivation(serviceWorker) {
serviceWorker.addEventListener('statechange', () => {
if (serviceWorker.state == 'activated') {
console.log('Installed new service worker.');
loadMainDartJs();
}
});
}
if (!reg.active && (reg.installing || reg.waiting)) {
// No active web worker and we have installed or are installing
// one for the first time. Simply wait for it to activate.
waitForActivation(reg.installing ?? reg.waiting);
} else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
// When the app updates the serviceWorkerVersion changes, so we
// need to ask the service worker to update.
console.log('New service worker available.');
reg.update();
waitForActivation(reg.installing);
} else {
// Existing service worker is still good.
console.log('Loading app from service worker.');
loadMainDartJs();
}
});
// If service worker doesn't succeed in a reasonable amount of time,
// fallback to plaint <script> tag.
setTimeout(() => {
if (!scriptLoaded) {
console.warn(
'Failed to load app from service worker. Falling back to plain <script> tag.',
);
loadMainDartJs();
}
}, 4000);
});
} else {
// Service workers not supported. Just drop the <script> tag.
loadMainDartJs();
}
</script>
<!-- Initialize Firebase -->
<script src="/__/firebase/9.0.2/firebase-app.js"></script>
<script src="/__/firebase/9.0.2/firebase-analytics.js"></script>
<script src="/__/firebase/init.js"></script>
<!-- Initialize app -->
<script src="main.dart.js?version=15 " type="application/javascript"></script>
</body>
</html>
Found an answer to the issue I was facing. Here is the link to the same:
Bootstrap Responsive Design Fails with Web Forwarding
This is because you are using a framed redirect which essentially loads up the target website in an iFrame. Doing so loses any responsive capabilities. What you are best doing is changing your web forwarding method to actually forward to the new URL using a non-framed redirect. This will then properly load up the target URL in the users browser and all the responsive capabilities that go with it.

How to setup less preprocessing in karma jasmine css testing

I'm making a 'simon says' game in javascript. I'm trying to setup a dev environment using Gulp supporting TDD. I'm using Jasmine run by Karma and am having a hard time getting started using the karma less preprocessor.
Project structure
build
css
app.min.css
js
app.min.ks
index.html
src
less
styles.less
js
script.js
index.html
test
js
scriptSpec.js
In my gulpfile I process less, babel and minify before putting it into the 'build' folder.
My index.html has one element. This element is passed to a 'createDom' js function, which creates all the elements for the game (board, buttons etc). Paths to styles and js is hardcoded like this:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Simon</title>
<!-- bower:css -->
<!-- endinject -->
<link rel="stylesheet" href="css/app.min.css">
</head>
<body>
<div id="simon"></div>
<script src="js/app.min.js"></script>
<script>
// DOM Ready
document.addEventListener("DOMContentLoaded", function() {
var el = document.getElementById('simon');
Simon.createDom(el);
});
</script>
<!-- bower:js -->
<!-- endinject -->
</body>
</html>
Simon.createDom() creates these elements:
<div id="simon">
<div class="board">
<div class="colorbox red" id="red" style="pointer-events: none;"></div>
<div class="colorbox green" id="green" style="pointer-events: none;"></div>
<div class="colorbox yellow" id="yellow" style="pointer-events: none;"></div>
<div class="colorbox blue" id="blue" style="pointer-events: none;"></div>
</div>
<h4 class="scoreFld">0</h4>
<h4 class="roundFld">0</h4><button class="btnStart">START</button>
</div>
I would like to test background colors of elements. But I cannot find out how to setup karma to be able to write a spec like this:
simonSpec.js
describe('playSequence()', function() {
var el,
sequence;
beforeEach(function () {
el = document.getElementById('simon');
Simon.createDom(el);
jasmine.clock().install();
sequence = ['red', 'green', 'blue'];
});
afterEach(function () {
jasmine.clock().uninstall();
sequence = [];
});
it('the first color should be red', function () {
Simon.playSequence(sequence);
var actual = document.getElementById('red').style.backgroundColor;
var expected = "rgb(255, 0, 0)";-color');
expect(actual).toEqual(expected);
});
})
The element with id 'red' is always undefined.
Can anyone point me to an example of how to set this up. I develop in less and would like to test before processing to css.
Karma executes your tests in the context of a dummy 'HTML' file which simply pulls in your tests as defined by the Karma config (files). That is what included in the Karma files configuration refers to. Hence, document.getElementById() is going to act on that dummy DOM and so it's not going to find your element.
What you need to do instead is load fixtures in your Jasmine tests that define the HTML to work with and then make your Simon game operate on your fixtures when executed through your Jasmine tests. Similarly your document.getElementById() logic should also be modified to operate on the fixtures instead.
Since you are using Jasmine already, consider using the Jasmine JQuery plugin which also adds support for working with fixtures in a convenient way.

What does the second argument of a gulp task mean:

I'm looking for an answer to this, doesn't have to be in depth or great detail. Just want to know exactly what happening with the sequence of the task.
gulp.task('name',['*this right here*'], function() {
// content
});
Does it mean do this task in consecutively namely with this definition task? Why this came up for me is because in my gulpfile.js I'm using gulp-inject for app files and wiredep for vendor dependencies. If this is wrong or either one will do then great, Im under the impression not though. What I have so far is below.
//originally i didn't have bower here in the array in 2nd param.
gulp.task('index', ['bower'], function() {
var target = gulp.src(files.app_files.target);
var sources = gulp.src(files.app_files.sources, {
read: false
});
return target.pipe(inject(sources))
.pipe(gulp.dest('./dist'));
});
gulp.task('bower', function() {
return gulp
.src(files.app_files.target)
.pipe(wiredep())
.pipe(gulp.dest('dist/'));
});
<head>
<meta charset="UTF-8">
<title>Example Page</title>
<!-- Vendor Files -->
<!-- bower:css -->
<!-- endbower -->
<!-- App Files -->
<!-- inject:css -->
<!-- endinject -->
</head>
<body>
<navigation></navigation>
<div ui-view></div>
<footer-area></footer-area>
<!-- Vendor Files -->
<!-- bower:js -->
<!-- endbower -->
<!-- App Files -->
<!-- inject:js -->
<!-- endinject -->
</body>
Update
gulp.task('index', function() {
var target = gulp.src(files.app_files.target);
// It's not necessary to read the files (will speed up things), we're only after their paths:
var sources = gulp.src(files.app_files.sources, {
read: false
});
return target
//here instead of breaking into new task i piped inject and wiredep, works great
.pipe(inject(sources))
.pipe(wiredep())
.pipe(gulp.dest('./dist'));
});
That's an array of tasks to run before your task.
Also, note those tasks (all the ones in the array, in you case there's only bower) run in parallel.
If you need some in sequence. Consider gulp-sequence

Gulp-Inject Positions

If I want to inject Js Files in diff. locations e.g. <head> here and here </body>. I need to set names like described here for the injections:
https://github.com/klei/gulp-inject#method-2-use-gulp-injects-name-option
<!-- head:js -->
<!-- only importantFile.js will be injected here -->
<!-- endinject -->
How can I modify this selector, that I don't have to name each file. E.g. take all files which contain *_important.js
.pipe(inject(gulp.src('./src/importantFile.js', {read: false}), {name: 'head'}))
And is there a better way. E.g. like adding s.th. inside the javascript file or name it like this orderModule.above.js, googleAnalytics.below.js
From the gulp documentation:
gulp.src(globs[, options]) - Emits files matching provided glob or an array of globs.
You therefore have tremendous freedom to define how you want to differentiate between "important" files and others.
.pipe(inject(gulp.src('*_important.js')))
.pipe(inject(gulp.src('*.head.js')))
etc. Then just provide the negation of this pattern in the second gulp.src call
.pipe(inject(gulp.src(['*.js', '!*_important.js'])))
.pipe(inject(gulp.src(['*.js', '!*.head.js'])))
gulp.task('dev', function () {
var target = gulp.src('./index.html');
return target
.pipe(inject(gulp.src('_MAIN_CSS_FILES_', {read: false})))
.pipe(inject(gulp.src('_BOWER_CSS_FILES_', {read: false}), {name: 'bower'}))
.pipe(inject(gulp.src('_MAIN_JS_FILES_', {read: false})))
.pipe(inject(gulp.src('_BOWER_JS_FILES_', {read: false}), {name: 'bower'}))
.pipe(gulp.dest("./dest/"));
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Index</title>
<!-- inject:css -->
<!-- built css files will go here... -->
<!-- endinject -->
<!-- bower:css -->
<!-- bower installed css files will go here... -->
<!-- endinject -->
</head>
<body>
<!-- bower:js -->
<!-- bower installed js files will go here... -->
<!-- endinject -->
<!-- inject:js -->
<!-- built js files will go here... -->
<!-- endinject -->
</body>
</html>

How to copy and inject the main-bower-files in one step using gulp?

When deploying my app I want to copy the bower dependency to the deploy directory and inject the links to these files into the index.html that is also in the deploy directory.
Each step alone works perfectly by I'm not able to combine them.
Copy the files:
return gulp.src(mainBowerFiles(), { read: false })
.pipe(gulp.dest('./deploy/lib/'));
Injecting the files:
return gulp.src('./deploy/index.html')
.pipe(plugins.inject(
gulp.src(mainBowerFiles(), { read: false }), { relative: true }))
.pipe(gulp.dest('./deploy/'));
I think that I should do this in one step to keep the correct order of the dependent files.
I tried this combination but it did not work out.
return gulp.src('./deploy/index.html')
.pipe(plugins.inject(
gulp.src(mainBowerFiles(), { read: false })
.pipe(gulp.dest('./deploy/lib/'), { relative: true })))
.pipe(gulp.dest('./deploy/'));
I recommend wiredep:
You add a block to your html:
<html>
<head>
</head>
<body>
<!-- bower:js -->
<!-- endbower -->
</body>
</html>
and your wiredep task looks like:
// inject bower components
gulp.task('wiredep', function () {
var wiredep = require('wiredep').stream;
gulp.src('app/*.html')
.pipe(wiredep())
.pipe(gulp.dest('app'));
});
Which will add the deps to your html as such:
<html>
<head>
</head>
<body>
<!-- bower:js -->
<script src="bower_components/foo/bar.js"></script>
<!-- endbower -->
</body>
</html>
You can then combine this with useref to order all your project's javascript dependencies
html block
<!-- build:js scripts/app.js -->
<!-- bower:js -->
<script src="bower_components/foo/bar.js"></script>
<!-- endbower -->
<script src="js/yourcustomscript.js"></script>
<!-- endbuild -->
gulp task
gulp.task('html', ['styles'], function () {
var assets = $.useref.assets({searchPath: '{.tmp,app}'});
return gulp.src('app/*.html')
.pipe(assets)
.pipe(assets.restore())
.pipe($.useref())
.pipe(gulp.dest('dist'));
});
Take a look at how generator-gulp-webapp does things: https://github.com/yeoman/generator-gulp-webapp
Note: the $.plugin syntax assumes var $ = require('gulp-load-plugins')();