-
Notifications
You must be signed in to change notification settings - Fork 25.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Single PWA with i18n #43796
Comments
We are currently using the following script to merge the service workers and unregister the old ones: const fs = require("fs");
const distFolder = "dist";
function getNgswConfig(locale) {
const swConfig = fs.readFileSync(`${distFolder}/${locale}/ngsw.json`);
return JSON.parse(swConfig);
}
const locales = fs
.readdirSync(distFolder)
.filter((locale) => fs.lstatSync(`${distFolder}/${locale}`).isDirectory());
// Merge the ngsw.json files
const firstLocale = locales.pop();
const combined = getNgswConfig(firstLocale);
locales.forEach((locale) => {
const additional = getNgswConfig(locale);
// Merge data and asset groups
const toBeMergedGroups = [
{ groupType: "dataGroups", property: "patterns" },
{ groupType: "assetGroups", property: "urls" },
];
toBeMergedGroups.forEach(({ groupType, property }) => {
additional[groupType].forEach((group) => {
combined[groupType]
.find((g) => g.name === group.name)
[property].push(...group[property]);
});
});
// combine hash tables
Object.assign(combined.hashTable, additional.hashTable);
fs.unlinkSync(`${distFolder}/${locale}/ngsw.json`);
fs.unlinkSync(`${distFolder}/${locale}/ngsw-worker.js`);
fs.renameSync(
`${distFolder}/${locale}/safety-worker.js`,
`${distFolder}/${locale}/ngsw-worker.js`
);
});
combined.index = "/index.html";
// add root index.html to correctly cache direct app entry (e.g. without en-US)
combined["assetGroups"][0]["urls"].push("/index.html");
fs.writeFileSync(`${distFolder}/ngsw.json`, JSON.stringify(combined));
fs.unlinkSync(`${distFolder}/${firstLocale}/ngsw.json`);
// Adjust service worker to allow changing language offline
const swFile = fs
.readFileSync(`${distFolder}/${firstLocale}/ngsw-worker.js`)
.toString();
const patchedSw = swFile.replace(
"return this.handleFetch(this.adapter.newRequest(this.indexUrl), context);",
`const locale = this.adapter.normalizeUrl(req.url).split("/")[1];
const url = locale ? "/" + locale + "/index.html": "/index.html";
return this.handleFetch(this.adapter.newRequest(url), context);`
);
fs.writeFileSync(`${distFolder}/ngsw-worker.js`, patchedSw);
fs.unlinkSync(`${distFolder}/${firstLocale}/ngsw-worker.js`);
fs.renameSync(
`${distFolder}/${firstLocale}/safety-worker.js`,
`${distFolder}/${firstLocale}/ngsw-worker.js`
); This script:
Additionally we register the service worker like this: ServiceWorkerModule.register("/ngsw-worker.js", {
enabled: environment.production,
}), And our manifest file has this config: {
"scope": "/",
"start_url": "/",
...
} More information can be found in this repo where we use this approach in production. |
Hi @TheSlimvReal - sorry not to respond so far on this issue. It is a bit tricky to implement on our side. I need to talk with @gkalpak about how this could work - I am not sure if it is something we would do. I am glad that for the time being you appear to have a workaround. |
This feature request is now candidate for our backlog! In the next phase, the community has 60 days to upvote. If the request receives more than 20 upvotes, we'll move it to our consideration list. You can find more details about the feature request process in our documentation. |
Can you clarify what the problem is for new users? Is it that when they arrive at |
No, the problem initially came from us adding One solution is to tell all users to reinstall the app which is a rather difficult process in our case and it might introduce the same problem again if we decide to remove |
Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends. Find more details about Angular's feature request process in our documentation. |
If you load your translation files at runtime using @angular/localize you can have a single pwa with multiple languages. You can still lazy load the translation files so that all languages are not part of your main bundle |
@kamshak What exactly are you revering to when you talk about at runtime? |
Yes, you can build separate application bundles for each language (inlining the translations). You use Another option is to ship translation files with your app and load them at run time (i.e. generate one app bundle + multiple files containing only the messages). That way Angular will keep the actual calls to |
@kamshak Thank you for pointing that out, I had no idea that this |
Have a PWA in production with this, it's working great so far |
@kamshak Sorry for the long silence. My previously mentioned workaround was working quite well but now we are running into some new problems regarding the service-workers and I would like to try out your approach. Just out of curiosity: How do you create your translation files for the |
Which @angular/* package(s) are relevant/releated to the feature request?
localize, service-worker
Description
Following up on this post on stackoverflow.
After adding internationalization (
i18n
) to our app we run into the big problem of backwards compatibility. Before addingi18n
we had our service worker at the root folder and after addingi18n
we now have a separate service worker for each language we translated the app into. This is a problem because a user that installed the app prior to this change will not correctly get updates because the old service worker will not be able to find the new service worker.This is the default behavior of Angular and left us with the decision that we either have to tell all our users that they will have to uninstall and re-install the app or add a service worker in the root folder that automatically takes care of the migration and leave it deployed until all users are migrated. Theses solutions are rather unsatisfying, poorly documented and mean that a we would have to go through the same struggle again if we decide to remove the
i18n
or take a different approach for it.Proposed solution
It would be great if Angular would not enforce to use the one-PWA-per-language approach but rather leave this as a choice to the developer. This would make the transition from a single- to a multi-language app much easier and leaves the option open to also go back to the previous approach (no
i18n
).This could be configured through the compiler options in the
angular.json
file. E.g.rootServiceWorker: true
.Alternatives considered
Alternatively, it would be great if Angular provided a guide or a predefined service worker (similar to the
safety-worker.js
) that allows a easy migration of the PWAs wheni18n
is introduced.The text was updated successfully, but these errors were encountered: