React-Snap with Create-React-App and Service Workers - react-snap

So, my understanding is that react-snap as per its features "Works out-of-the-box with create-react-app - no code-changes required."
I read through the documentation and I see that it required some adjusting to work with Google Analytics which I implemented.
However, it also suggests changes to be made if one is going to use the default service worker that comes with CRA.
https://github.com/stereobooster/react-snap#service-workers
However, what is confusing is that it seems one has to perform a EJECT in order to make the necessary change.
navigateFallback: publicUrl + '/index.html',
You need to change this to an un-prerendered version of index.html - 200.html, otherwise you will see index.html flash on other pages (if you have any). See Configure sw-precache without ejecting for more information.
My question is - and note I am quite novice - does one have to eject? I kinda want to keep things simple. The only place I could find this line was in WebPack. navigateFallback
Also, if I don't see the negative side of the flashes on pages as per the documentation, is it okay to omit this step or will it have issues on other things?

Although this question is more than a year old, I'd like to take the opportunity as I've been able to implement service workers in react-snap (although with a varying degree of success).
Here's stereobooster's reference in GitHub:
https://github.com/stereobooster/react-snap/blob/master/doc/recipes.md#configure-sw-precache-without-ejecting
You can configure it without ejecting. What you need to do is the following:
Download and install sw-precache and ugfify-js:
npm install sw-precache uglify-js --save-dev
or
yarn add sw-precache uglify-js -D
Then, in your package.json add the following entries:
(Replace the build script with the following)
"scripts": {
"generate-sw": "sw-precache --root=build --config scripts/sw-precache-config.js && uglifyjs build/service-worker.js -o build/service-worker.js",
"build": "react-scripts build && react-snap && yarn run generate-sw"
}
Then, create a folder in the root level (next to your package.json) called scripts
and add sw-precache-config.js file.
module.exports = {
// a directory should be the same as "reactSnap.destination",
// which default value is `build`
staticFileGlobs: [
"build/static/css/*.css",
"build/static/js/*.js",
"build/shell.html",
"build/index.html"
],
stripPrefix: "build",
publicPath: ".",
// there is "reactSnap.include": ["/shell.html"] in package.json
navigateFallback: "/shell.html",
// Ignores URLs starting from /__ (useful for Firebase):
// https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219
navigateFallbackWhitelist: [/^(?!\/__).*/],
// By default, a cache-busting query parameter is appended to requests
// used to populate the caches, to ensure the responses are fresh.
// If a URL is already hashed by Webpack, then there is no concern
// about it being stale, and the cache-busting can be skipped.
dontCacheBustUrlsMatching: /\.\w{8}\./,
// configuration specific to this experiment
runtimeCaching: [
{
urlPattern: /api/,
handler: "fastest"
}
]
};
Note, if you're not using an app-shell but you're loading the whole page (Meaning there's no dyanmic content), replace where it says navigateFallback: "/shell.html" with navigateFallback: "/200.html"
This basically allows you to cache the entire page
You can look for more information here:
https://github.com/stereobooster/an-almost-static-stack
One thing that I'd recommend to check (I'm close to start that process as well) is the workbox-sw.
What to do if React-Snap fails
error at / TypeError: Cannot read property 'ok' of null
Or
ERROR: The process with PID 38776 (child process of PID 26920) could not be terminated. \node_modules\minimalcss\src\run.js:13:35)
Reason: There is no running instance of the task.
You may get these infamous errors. I don't know exactly what causes them, but I know they're mentioned here, and here. In this case, delete the build folder, open a new terminal window, and try again.
If the problem still persists, then break down the script:
Do:
"scripts": {
"build": "react-scripts build"
"postbuild": "react-snap",
"generate-sw": "sw-precache --root=build --config scripts/sw-precache-config.js && uglifyjs build/service-worker.js -o build/service-worker.js",
}
And try running them independently.

Related

How to get path excludes working in Madge?

I'm trying to run madge on a fairly big typescript project. Its compiled output goes to dist/*, and its React frontend are in public/*. Madge's documentation is pretty clear about how to exclude directories, but no matter what I try, it appears to still be checking these directories.
First attempt:
madge --circular --extensions ts,js --exclude '^(dist|public)' --ts-config ./tsconfig.json --warning .
The reason I think it's still checking there is because, first, I still see it scanning those directories as it runs:
And also, its warnings show imports that only occur in public/:
(the '#'-style import is from module-alias)
What I've tried:
Using a regex like ^.*public.*$
Specifying the excludes in .madgerc rather than on cli:
{
"fileExtensions": ["js","ts"],
"tsConfig": "tsconfig.json",
"excludeRegExp": ["^.*dist.*$", "^.*public.*$"]
}
Running with --debug (the output is so massive I can't really make much of it - if I run it to console it crashes with out-of-memory, and if I pipe to a file, it gets so big that it literally fills up my SSD - I had to cancel when the log file surpassed 25 gigs).
Interestingly, it doesn't seem to be reporting any cycles in public/ or dist/, so I think it might be "partially" working. However, it does still seem to be scanning & processing those excluded paths, so I can't get rid of all the warnings that shouldn't be relevant to this run.

parcel watch only detects first file change

I have the following in ./js/parcel/build-js.js (it is more or less a simplification of exactly what the API docs example does, except that it takes an optional --watch argument):
#!/usr/bin/env node
const Bundler = require('parcel-bundler');
const path = require('path');
const watch = process.argv.indexOf('--watch') > 0;
if (watch) console.log('Watching files...');
(async function bundleJs() {
const jsBundler = new Bundler(path.join(__dirname, '../src/common.js'), {
watch,
hmr: false,
});
jsBundler.on('bundled', () => {
console.log('bundled!');
});
const bundle = await jsBundler.bundle();
console.log('done');
})();
When I run node js/parcel/build-js.js --watch, it detects the first change to src/common.js and prints:
Watching files...
✨ Built in 585ms.
bundled!
done
This is as I'd expect. When I edit and save src/common.js, it sees that and then the total output becomes (done gets deleted):
Watching files...
✨ Built in 585ms.
bundled!
✨ Built in 86ms.
bundled!
But after that, no file changes are detected. I make changes and save but it just sits there, producing no more output or updating the build. Why only once?
Note: If I do strace node js/parcel/build-js.js --watch, it seems to just sit on an unfinished epoll_wait(3,, which I guess means it's waiting for something, but maybe watching the wrong file...
Edit: Versions!
parcel-bundler: 1.12.3
node: 10.15.1
Ubuntu 18.04
Edit: using parcel watch
This appears to be a system-wide thing for me. I did yarn globals add parcel (which also installed 1.12.3), and now watching any JS file with parcel watch path/to/file.js does the same thing.
It turned out to be a conflict between Parcel's change detection and the default Vim setup. From the Hot Module Replacement docs:
Some text editors and IDE's have a feature called safe write that basically prevents data loss, by taking a copy of the file and renaming it when saved.
When using Hot Module Reload (HMR) this feature blocks the automatic detection of file updates, to disable safe write use the options provided below:
I added set backupcopy=yes to my .vimrc and it started working.
The solution for other editors is documented there as well.
It is a Parcel issue! I dropped it (until they fix it)
IMHO: I do not have to change my editor's behavior just to make bundler work correctly. (webpack works fine in the situation)

How can I get "HelloWorld - BitBake Style" working on a newer version of Yocto?

In the book "Embedded Linux Systems with the Yocto Project", Chapter 4 contains a sample called "HelloWorld - BitBake style". I encountered a bunch of problems trying to get the old example working against the "Sumo" release 2.5.
If you're like me, the first error you encountered following the book's instructions was that you copied across bitbake.conf and got:
ERROR: ParseError at /tmp/bbhello/conf/bitbake.conf:749: Could not include required file conf/abi_version.conf
And after copying over abi_version.conf as well, you kept finding more and more cross-connected files that needed to be moved, and then some relative-path errors after that... Is there a better way?
Here's a series of steps which can allow you to bitbake nano based on the book's instructions.
Unless otherwise specified, these samples and instructions are all based on the online copy of the book's code-samples. While convenient for copy-pasting, the online resource is not totally consistent with the printed copy, and contains at least one extra bug.
Initial workspace setup
This guide assumes that you're working with Yocto release 2.5 ("sumo"), installed into /tmp/poky, and that the build environment will go into /tmp/bbhello. If you don't the Poky tools+libraries already, the easiest way is to clone it with:
$ git clone -b sumo git://git.yoctoproject.org/poky.git /tmp/poky
Then you can initialize the workspace with:
$ source /tmp/poky/oe-init-build-env /tmp/bbhello/
If you start a new terminal window, you'll need to repeat the previous command which will get get your shell environment set up again, but it should not replace any of the files created inside the workspace from the first time.
Wiring up the defaults
The oe-init-build-env script should have just created these files for you:
bbhello/conf/local.conf
bbhello/conf/templateconf.cfg
bbhello/conf/bblayers.conf
Keep these, they supersede some of the book-instructions, meaning that you should not create or have the files:
bbhello/classes/base.bbclass
bbhello/conf/bitbake.conf
Similarly, do not overwrite bbhello/conf/bblayers.conf with the book's sample. Instead, edit it to add a single line pointing to your own meta-hello folder, ex:
BBLAYERS ?= " \
${TOPDIR}/meta-hello \
/tmp/poky/meta \
/tmp/poky/meta-poky \
/tmp/poky/meta-yocto-bsp \
"
Creating the layer and recipe
Go ahead and create the following files from the book-samples:
meta-hello/conf/layer.conf
meta-hello/recipes-editor/nano/nano.bb
We'll edit these files gradually as we hit errors.
Can't find recipe error
The error:
ERROR: BBFILE_PATTERN_hello not defined
It is caused by the book-website's bbhello/meta-hello/conf/layer.conf being internally inconsistent. It uses the collection-name "hello" but on the next two lines uses _test suffixes. Just change them to _hello to match:
# Set layer search pattern and priority
BBFILE_COLLECTIONS += "hello"
BBFILE_PATTERN_hello := "^${LAYERDIR}/"
BBFILE_PRIORITY_hello = "5"
Interestingly, this error is not present in the printed copy of the book.
No license error
The error:
ERROR: /tmp/bbhello/meta-hello/recipes-editor/nano/nano.bb: This recipe does not have the LICENSE field set (nano)
ERROR: Failed to parse recipe: /tmp/bbhello/meta-hello/recipes-editor/nano/nano.bb
Can be fixed by adding a license setting with one of the values that bitbake recognizes. In this case, add a line onto nano.bb of:
LICENSE="GPLv3"
Recipe parse error
ERROR: ExpansionError during parsing /tmp/bbhello/meta-hello/recipes-editor/nano/nano.bb
[...]
bb.data_smart.ExpansionError: Failure expanding variable PV_MAJOR, expression was ${#bb.data.getVar('PV',d,1).split('.')[0]} which triggered exception AttributeError: module 'bb.data' has no attribute 'getVar'
This is fixed by updating the special python commands being used in the recipe, because #bb.data was deprecated and is now removed. Instead, replace it with #d, ex:
PV_MAJOR = "${#d.getVar('PV',d,1).split('.')[0]}"
PV_MINOR = "${#d.getVar('PV',d,1).split('.')[1]}"
License checksum failure
ERROR: nano-2.2.6-r0 do_populate_lic: QA Issue: nano: Recipe file fetches files and does not have license file information (LIC_FILES_CHKSUM) [license-checksum]
This can be fixed by adding a directive to the recipe telling it what license-info-containing file to grab, and what checksum we expect it to have.
We can follow the way the recipe generates the SRC_URI, and modify it slightly to point at the COPYING file in the same web-directory. Add this line to nano.bb:
LIC_FILES_CHKSUM = "${SITE}/v${PV_MAJOR}.${PV_MINOR}/COPYING;md5=f27defe1e96c2e1ecd4e0c9be8967949"
The MD5 checksum in this case came from manually downloading and inspecting the matching file.
Done!
Now bitbake nano ought to work, and when it is complete you should see it built nano:
/tmp/bbhello $ find ./tmp/deploy/ -name "*nano*.rpm*"
./tmp/deploy/rpm/i586/nano-dbg-2.2.6-r0.i586.rpm
./tmp/deploy/rpm/i586/nano-dev-2.2.6-r0.i586.rpm
I have recently worked on that hands-on hello world project. As far as I am concerned, I think that the source code in the book contains some bugs. Below there is a list of suggested fixes:
Inheriting native class
In fact, when you build with bitbake that you got from poky, it builds only for the target, unless you mention in your recipe that you are building for the host machine (native). You can do the latter by adding this line at the end of your recipe:
inherit native
Adding license information
It is worth mentioning that the variable LICENSE is important to be set in any recipe, otherwise bitbake rises an error. In our case, we try to build the version 2.2.6 of the nano editor, its current license is GPLv3, hence it should be mentioned as follow:
LICENSE = "GPLv3"
Using os.system calls
As the book states, you cannot dereference metadata directly from a python function. Which means it is mandatory to access metadata through the d dictionary. Bellow, there is a suggestion for the do_unpack python function, you can use its concept to code the next tasks (do_configure, do_compile):
python do_unpack() {
workdir = d.getVar("WORKDIR", True)
dl_dir = d.getVar("DL_DIR", True)
p = d.getVar("P", True)
tarball_name = os.path.join(dl_dir, p+".tar.gz")
bb.plain("Unpacking tarball")
os.system("tar -x -C " + workdir + " -f " + tarball_name)
bb.plain("tarball unpacked successfully")
}
Launching the nano editor
After successfully building your nano editor package, you can find your nano executable in the following directory in case you are using Ubuntu (arch x86_64):
./tmp/work/x86_64-linux/nano/2.2.6-r0/src/nano
Should you have any comments or questions, Don't hesitate !

npm start runs but no output

I got a simple program off github 1 crlint.js that takes a js file and creates a report identifying various measures like Cyclomatic complexity and Halstead value. I updated my node and npm (I'm on a Mac - Sierra). I added a start line in the script section of the package.json file:
"scripts": {
"start": "node crlint",
"test": "echo \"There is an Error: no test specified\" && exit 1"
}
When I run it in the terminal (input file lib/testutil.js), no errors but no report generated either.
npm start [cyclomatic] —lib/toolutil.js
This comes back (in the terminal):
> crlint#0.1.1 start /Users/cindy/Documents/crlint
> node crlint "lib/toolutil.js"
Any thoughts? This is the first time I've used github so am sure I am missing something. I've looked at the posts on this forum about this - didn't find anything useful. Thanks -

How do I define an extension for coffeeify with Budo dev server?

I'm trying to use coffeeify with budo so I do not have to add the extension to my require statements. I have tried passing these commands through budo's browserify options
budo src/app.coffee --live --serve bundle.js -- -t coffeeify --extension=".coffee"
budo src/app.coffee --live --serve bundle.js -- -t [coffeeify --extension=".coffee"]
I also tried inserting the browserify transform into my package.json
"browserify: {
"transform": ["coffeeify", {"extension": ".coffee"}]
}
Here is something that works for me (took me forever to figure it out, the hard part being getting watchify to work with coffeescript). Everything is in the package.yaml. Invoke npm start from your top folder and it will do the trick. npm puts all the locally installed node binaries in your PATH for you (they normally live under node_modules/.bin).
{
"name": "my-package",
"version": "1.0.0",
"private": true,
"scripts": {
"start": "(cd src; budo app.coffee:bundle.js --dir . --live --verbose -- --extension=.coffee | garnish)"
},
"browserify": {
"extension": [ ".coffee" ],
"transform": [ ["coffeeify"], ["brfs"] ]
},
"devDependencies": {
"brfs": "1.4.1",
"browserify": "11.1.0",
"budo": "^5.1.5",
"coffee-script": "latest",
"coffeeify": "^1.1.0",
"garnish": "^3.2.1",
"watchify": "3.4.0"
}
}
I have my source code under the src folder, and a file named app.coffee which includes (or require in node.js terms) my whole application. I have an index.html in my src folder which reference the bundle.js through from an html script tag.
The command to start budo is inside my package.json. It does cd into my src folder first.
The trick is to specify some configuration in the browserify block: the extension .coffee needs to be present, and a list of transforms as well. I tried to have everything on the command line but never got it to work
After npm start is invoked, since I pass the --live argument to budo everything works like magic and edit/saves to my documents do trigger a browser reload/refresh.
To deploy or release you'll probably need another target to minify with uglify.js. I still have a script that does that manually in 2 steps, the first step calls browserify and the second step calls uglify.js explicitely.
As a remark, recent version of budo do the piping into garnish for you I've heard.
Another tip is to look at what the React folks are doing to transform their .jsx files, as it is in theory extremely close to what the coffeescript folks need to do. There seems to be a huge momentum around React so hopefully React people will have figured those build problems first.