I'm trying to configure Workbox in CRA without eject. Anyone succeeded?
After hours trialing and error I succeeded to have workbox in CRA. Here's how I did:
First,yarn add -D workbox-build
Next, create a file called build-sw.js in the root folder with:
const fs = require('fs-extra');
const pathmodule = require('path');
const workbox = require('workbox-build');
function build() {
const cwd = process.cwd();
const pkgPath = `${cwd}/node_modules/workbox-sw/package.json`;
const pkg = require(pkgPath);
const readPath = `${cwd}/node_modules/workbox-sw/${pkg.main}`;
let data = fs.readFileSync(readPath, 'utf8');
let path = `${cwd}/build/workbox-sw.js`;
console.log(`Writing ${path}.`);
fs.writeFileSync(path, data, 'utf8');
data = fs.readFileSync(`${readPath}.map`, 'utf8');
path = `${cwd}/build/${pathmodule.basename(pkg.main)}.map`;
console.log(`Writing ${path}.`);
fs.writeFileSync(path, data, 'utf8');
workbox
.injectManifest({
globDirectory: 'build',
globPatterns: ['**/*.{html,js,css,png,jpg,json}'],
globIgnores: ['sw-default.js', 'service-worker.js', 'workbox-sw.js'],
swSrc: './src/sw-template.js',
swDest: 'build/sw-default.js'
})
.then(_ => {
console.log('Service worker generated.');
});
}
try {
build();
} catch (e) {
console.log(e);
}
After that, create a file in src/sw-template.jswith:
(Have in mind that in this file is where you have to put your own cache strategy. See Docs for more info)
workbox.setConfig({
debug: true
});
workbox.core.setLogLevel(workbox.core.LOG_LEVELS.debug);
workbox.precaching.precacheAndRoute([]);
workbox.skipWaiting();
workbox.clientsClaim();
workbox.routing.registerRoute('/', workbox.strategies.networkFirst());
Finally, in src/registerServiceWorker.js change:
- const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
+ const swUrl = `${process.env.PUBLIC_URL}/sw-default.js`;
And in package.json change:
- "build": "react-scripts build && sw-precache --config=sw-precache-config.js'",
+ "build": "react-scripts build && yarn sw",
+ "sw": "node build-sw.js"
Hope it helps!
With the merge of this PR, Create React App 2 now support supports Workbox out of the box, since it now uses workbox-webpack-plugins internally.
Take a look at the official docs to learn more: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
Related
I need to build and deploy a React / NextJS app to a Weblogic J2ee server with a specific context. I have some React experience, but taking my first steps with NextJS.
Currently the build/verification steps are;
Create a vanilla NextJS app
Add a next.config.js with a module.export to change the basepath
module.exports = {
basePath: '/test'
}
Execute npm run dev the application is available on 'http://localhost:3000/test'
Add an export script to the package.json "export": "next build && next export" to support static export
Add the export below to resolve issue 21079
//https://github.com/vercel/next.js/issues/21079
module.exports = {
images: {
loader: "imgix",
path: "",
}
}
Executed npm run export to create a static HTML export. Export is completed successfully to the out folder.
When inspecting the index.html in the out folder, all references to the static content still starts with /_next/static and not with /test/_next/static.
So this can be a misinterpretation of my side, please correct me if i am wrong here.
To be able to test the vanilla app on the J2EE applicationserver it has to be packed into a war file. To accomplish this i added the file warpack/warpack.ts to the project.
const fs = require('fs');
const archiver = require('archiver');
const rimraf = require('rimraf') ;
const distFolder = 'dist' ;
const warFile = distFolder + '/test.war';
const buildFolder = 'out';
const contextRoot = 'test';
// Destroy dist folder
rimraf(distFolder, (error) => {
if (!error) {
// Create dist folder
if (!fs.existsSync(distFolder)){
fs.mkdirSync(distFolder);
}
const output = fs.createWriteStream(warFile);
const archive = archiver('zip', {});
output.on('close', () => {
console.log('war (' + warFile + ') ' + archive.pointer() + ' total bytes');
});
// write archive to output file
archive.pipe(output);
// add build folder to archive
archive.directory(buildFolder,'');
// add weblogic.xml
const weblogicXML = '<?xml version="1.0" encoding="UTF-8"?><weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.2/weblogic-web-app.xsd"><weblogic-version>10.3.6</weblogic-version><context-root>' + contextRoot '</context-root><description>Test NextJS</description></weblogic-web-app>'
archive.append(weblogicXML,{ name: 'WEB-INF/weblogic.xml' });
const manifestMF = 'Manifest-Version: 1.0\nBuild-Tag: 0.0.1-SNAPSHOT\nWeblogic-Application-Version: 0.0.1-SNAPSHOT';
archive.append(manifestMF,{ name: 'META-INF/MANIFEST.MF' });
archive.finalize();
} else {
console.log('Failed to delete "' + distFolder + '" folder.') ;
process.exit(1);
};
});
Installed the required packages for webpack.ts
npm install fs --save-dev
npm install rimraf --save-dev
npm install archiver --save-dev
Added the script "warpack": "next build && next export && node warpack/warpack.ts" to build, export and pack the static app to an war.
After deployment of the war-file the page can be loaded on http://something/test but shows an empty page.
Network development tools indicate that the requests are made to the root of the application server, not to the configured basepath.
GET http://host:8001/static/css/main.09371e9d.chunk.css net::ERR_ABORTED 404 (Not Found)
GET http://host/static/js/2.0850eeb7.chunk.js net::ERR_ABORTED 404 (Not Found)
GET http://host/static/js/main.dc0c945b.chunk.js net::ERR_ABORTED 404 (Not Found)
Too much focus on basePath value instead on correct syntax of next.config.js.
Second module export in next.config.js overwrote first.
Wrong
module.exports = {
basePath: '/test'
}
//https://github.com/vercel/next.js/issues/21079
module.exports = {
images: {
loader: "imgix",
path: "",
}
}
Correct
module.exports = {
basePath: '/test',
assetPrefix: "/test/",
//https://github.com/vercel/next.js/issues/21079
images: {
loader: "imgix",
path: ""
}
}
You can use env check to invoke only for prod environment if you wish to like:
module.exports = {
basePath: "/test"
assetPrefix: process.env.NODE_ENV === "production" ? "/test/" : undefined,
}
I have an app in angularjs that uses nodejs and I am looking for some ideas to improve the configuration for the appConfig files
In these files I have some fields like
feature1 = false;
feature2 = false
I am using these values to show/hide some buttons/panels on different pages but I have 1 config file for each client I would like to reduce the number of config files or to improve this
Not sure if it's an angular specific question but in my Nuxt projects a have a script that generate a config file before app launch.
That script will generate a config file which contain a base config and some project specific options.
Maybe this approach will be helpful for you.
config/base.js
module.exports = {
api: '/api-path',
someFeature: true,
anotherFeature: true
};
config/production.js
module.exports = {
someFeature: false
};
config/clientOne.js
module.exports = {
anotherFeature: false
};
tools/config.js
const fs = require('fs');
const base = require('../config/base');
const production = require('../config/production');
const dev = require('../config/dev');
const clientOne = require('../config/clientOne');
const clientTwo = require('../config/clientTwo');
let result = Object.assign({}, base);
let map = {
production,
dev,
clientOne,
clientTwo
};
result = Object.assign({}, result, map[ process.env.NODE_ENV ]);
fs.writeFileSync('./static/config.json', JSON.stringify(result));
package.json
{
"scripts": {
"start:production": "cross-env NODE_ENV=production node ./tools/config.js && nuxt start",
"start:dev": "cross-env NODE_ENV=dev node ./tools/config.js && nuxt",
"start:clientOne": "cross-env NODE_ENV=clientOne node ./tools/config.js && nuxt",
"start:clientTwo": "cross-env NODE_ENV=clientTwo node ./tools/config.js && nuxt"
}
}
Hello Stackoverflow users!
I am trying to place all of the configuration for the electron app in the package.json file.
Here is my code snippet:
index.js
const { app, BrowserWindow, ipcMain } = require('electron');
const fs = require('fs');
function readConf() {
const data = fs.readFileSync('./package.json', 'utf8');
return data;
}
ipcMain.on('synchronous-message', (event, arg) => {
event.returnValue = readConfig();
})
index.html
<script type="text/javascript">
const { ipcRenderer } = require('electron')
config = JSON.parse(ipcRenderer.sendSync('synchronous-message', ''))
</script>
<h1>Version of <script>document.write(config.name)</script> is <script>document.write(config.version);</script></h1>
The code is working when you run the app via npm start, but when you make it into an exe with electron-forge and squirrel (npm make) and try to run it after installing it throws an error that the package.json file can't be found.
So what do you need to specify as the path to the file to read it in the built app?
I am using electron forge.
I found a way to fix the issue!
Instead of
const data = fs.readFileSync('./package.json', 'utf8');
You'll need to write
const data = fs.readFileSync(__dirname + '/../package.json', 'utf8');
I am new to react and there is a problem while solving the error.
May I ask please what is missing in my project environment please?
The following message appears:
**Failed to compile**
./node_modules/#testing-library/dom/node_modules/pretty-format/build/plugins/DOMCollection.js
Module parse failed: Unexpected token (53:15)
You may need an appropriate loader to handle this file type.
| return props;
| }, {})
| : {...collection},
| config,
| indentation,
webpack.config.dev.js file:
This file is being generated after the npm run eject command.
'use strict';
const autoprefixer = require('autoprefixer');
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const eslintFormatter = require('react-dev-utils/eslintFormatter');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getClientEnvironment = require('./env');
const paths = require('./paths');
I don't know if it is a good long term solution but I was having this issue and changed react-scripts to version 4.0.1 with npm install react-scripts#4.0.1 and my dev environment is up again.
Okay, so the first step is having the DOMCollection.js file opened and then resolving the {...collection} to collection,
Save the file and reload the page.DOMCollection
so from : {...collection}
config,
indentation,
depth,
refs,
printer
to :
collection,
config,
indentation,
depth,
refs,
printer
I have the following gulp task that returns a stream. It works fine in gulp 3.9.1, but converting to gulp 4.0, I get:
Did you forget to signal async completion?
const gulp = require('gulp');
const gulpif = require('gulp-if');
const plumber = require('gulp-plumber');
const rename = require('gulp-rename');
const buffer = require('vinyl-buffer');
const es = require('event-stream');
const browserify = require('browserify');
const browserifyInc = require('browserify-incremental');
const babelify = require('babelify');
const browserSync = require('browser-sync').create();
// Incrementally building the js
gulp.task('build-js-inc', () =>
es.merge.apply(null, paths.entry.scripts.map(script => {
const b = browserify(Object.assign({}, browserifyInc.args,
{
entries: script,
extensions: ['.jsx'],
debug: true
}
));
browserifyInc(b, { cacheFile: './browserify-cache.json' });
return b.transform(babelify)
.bundle()
.on('error', handleErrors)
.pipe(source(`./${script.split('/')[script.split('/').length - 1]}`))
.pipe(buffer())
.pipe(plumber())
.pipe(rename(path => {
path.extname = '.bundle.js';
}))
.pipe(gulp.dest('public/js'))
.pipe(gulpif('*sw.bundle.js', gulp.dest('public')))
.pipe(browserSync.reload({ stream: true }));
}))
);
I've tried adding done() to my upstream tasks, but it still errors because I'm thinking it originates here and propogates through my subsequent tasks that rely on this one finishing.
The problem ended up being the module event-stream. Apparently it is no longer being maintained.
#phated:
Support for event-stream is deprecated. Everything is supposed to move to through2, et al. Maybe just fully deprecate this module?
I switched to merge-stream and now my gulpfile works fine.