Closed BlindDespair closed 4 years ago
Actually using --baseFilter
CLI argument is not working. Scully is then unable to find any routes. So in the end my alternative solution is not working unfortunately. That makes sense because --baseFilter
is supposed to be a route, it's not same as baseHref. But problem is that there doesn't seem to be an option to tell scully about baseHref currently.
@BlindDespair Thanks for the issue. I will look into this. Can you explain why you need a different base-ref for every language? That part is still unclear to me. I do have a couple of ideas on how to "fix" his issue.
@SanderElias Different base href is needed because the directories are generated per locale, which means you have a different angular application per locale. There are only 2 ways to tell webserver which angular app to use for which locale:
I am going to stick with subdirectories for this, thus need baseHref.
Hi @SanderElias, I also really need this support. Is there any progress? At least passing arguments to scully.config.js could be very useful. Thank you in advance
@BlindDespair have the same build with i18n... and configured all similar to your stuff. The problem now is that when the angular project was built with --localize flag, the baseHref's are automatically set to the respective language, but in this case scully can't parse the pages correctly in my case which results, that the <app-root>
element in the generated index.html files from scully has no childs. Do you have the same issues, or is this working in your project?
@SanderElias The different baseHref is automatically set by angular, when the --localize flag is set. For example, you have two languages configured in your i18n config part in the angular.json (de + en), then angular builds two separate projects into subfolders dist/project/de + dist/project/en and automatically sets the baseHref to /de/ and /en/ for the respective language projects
Also stuck on this, too bad I really wanted to try to statically render our site.. does anyone know of a workaround for this? Even having a separate scully config for each locale (with an outdir specification) would be good enough
Also stuck on this, too bad I really wanted to try to statically render our site.. does anyone know of a workaround for this? Even having a separate scully config for each locale (with an outdir specification) would be good enough
Yeah but there's another issue with parameterized scully config and the localized sites are not correctly parsed. Also trying to workaround it the last days...
@dyingangel666 I don't have a working solution yet because there is no chance to tell scully what baseHref
to use. I am still waiting for this too. We need multilanguage support on our site, but it's not high prio.
@dyingangel666 I don't have a working solution yet because there is no chance to tell scully what
baseHref
to use. I am still waiting for this too. We need multilanguage support on our site, but it's not high prio.
Yeah same here....But for me it's very important because it's a marketplace site. Trying another thing tomorrow to workaround the issue... Maybe I have luck 😅 the scully build works correctly when the baseHref is set to "/" but then some other stuff can't be referenced. My idea is to set the baseHref and then use a post script to change it back to the correct one like "/de/" after it's successfully built
So found a workaround that is working. Not the best solution, but until there's a fix from scully side, it's the best option for now:
scully.config
require('./postrender-plugins/i18nBaseHrefFix');
exports.config = {
projectRoot: "./src",
defaultPostRenderers: [
'i18nBaseHrefFix'
],
projectName: "marketplace-frontend",
outDir: `./dist/static/${process.env.LOCALE}`,
distFolder: `./dist/marketplace-frontend/${process.env.LOCALE}`,
routes: {
'/products/:productId': {
type: 'json',
productId: {
url: 'http://localhost:1668/assets/products.json',
property: 'id'
}
}
},
reloadPort: 4200,
puppeteerLaunchOptions: {
args: ['--no-sandbox', '--disable-setuid-sandbox']
}
};
i18nBaseHrefFix.js
const {registerPlugin} = require('@scullyio/scully');
const i18nBaseHrefFixPlugin = async (html) =>
{
const regex = new RegExp(`(<base href=")(\\/)(">)`, 'gmi');
html = html.replace(regex, `$1/${process.env.LOCALE}/$3`);
return Promise.resolve(html);
};
registerPlugin('render', 'i18nBaseHrefFix', i18nBaseHrefFixPlugin);
module.exports.i18nBaseHrefFixPlugin = i18nBaseHrefFixPlugin;
angular.json (i18n config)
"i18n": {
"sourceLocale": {
"code": "de",
"baseHref": "/"
},
"locales": {
"en": {
"translation": "src/locales/messages.en.xlf",
"baseHref": "/"
}
}
}
It's important to set the baseHref for each language to "/" because then scully parses all pages correctly and the index.html files have all the static content. The postrenderer script then sets the baseHref correctly back to the respective language, so that all references are still working. The scully config is parametrized (thx for @BlindDespair for this idea) ;-)
Cheers
I have released a base-href-rewrite plugin,(#610) that should take care of most of the concerns here. (instructions)
@SanderElias let's have some more conversation with the people on this issue. Let's see if the baseHrefRewrite functionality gets them what they need. If so, let's close this. If not, let's finish building what they need for i18n.
@BlindDespair can you comment here on your latest progress or lack thereof? We want to fix this, but need you to give feedback here. We think we may be done. But we also think there may be a few more things you need from us. We need to understand this.
@aaronfrost I can try out the baseHref plugin some time during the weekend to see if it's enough for me. If it works, I think I will be happy with it. I think prerendering for each language separately actually gives an advantage because you may not always need to regenerate all of them and run jobs for each language in parallel even on different runners. I will write as soon as I check it.
I tried it out, but so far I haven't managed to get it to work. When I use the base href plugin the pages just don't get prerendered. I did the following:
ng build --localize --stats-json -c staging
(generates angular with all locals, e.g. ./dist/frontend/uk
)defaultPostRenderers: [baseHrefRewrite]
(also added this line setPluginConfig(baseHrefRewrite, { href: process.env.BASE_HREF });
)distFolder: `./dist/frontend/${process.env.LOCALE}`,
to get the desired language's angular buildSCULLY_ENV=staging LOCALE=uk npx scully --scanRoutes
The prerendering is running, but appears to be very slow. After the generation is over index.html
filles contain no prerendered DOM. Just the basic index.html
of angular. And because of that data.json
wasn't generated. Thus when serving scully build it's not working at all. I tried running with --showBrowser
and saw that the URL used didn't icnlude baseHref and the generation didn't even succeed. If you can somehow help me solving it, would be great.
Some more notes: I believe it's possible to make a working i18n using what's available in scully assuming it works, but I do see certain inconviniences.
dotenv
. Information about what baseHref
is needed and what is the dist subfolder is already there in angular.json
. Ideally scully could read it. I would need at least 2 dotenv
variables: LOCALE
for dist subpath and passing to plugins and BASE_HREF
for passing it to baseHref rewrite plugin because it might not always be the same.
See my angular.json
i18n:
"i18n": {
"sourceLocale": { "code": "ru", "baseHref": "/" }, // BASE_HREF = '/', LOCALE = 'ru'
"locales": {
"uk": "", // BASE_HREF = 'uk', LOCALE = 'uk'
"en": "" // // BASE_HREF = 'en', LOCALE = 'en'
}
},
dist/static
. This is not too bad, but it requires an extra step on the CI to move the files, because I think the desired structure would be something like dist/static/:locale
, because that's how in the last job, I'll just copy over the whole static
folder to my server.'/menu/:categorySlug': {
type: 'json',
categorySlug: {
url: `${process.env.API_BASE_URL}menu/categories?lang=${[process.env.LOCALE}`,
property: 'urlSegment',
},
},
Since I am using dotenv
here, currently it is not a problem, however, if scully was using angular.json
and I wouldn't need dotenv
there how would I be able to get locale?
To sum up:
Best would be if scully had a simple config to handle i18n stuff in just a couple of steps without having scully user doing multiple manual steps, however, use cases like in note 3 would need to be considered.
The most desired CLI imo would look something like npx scully --locale uk
(everything else is already in angular.json
) if no locale is specified, then the default should be used (like here: "sourceLocale": { "code": "ru", "baseHref": "/" },
).
@SanderElias what are your thoughts?
@BlindDespair The plugin alters the base-href after rendering. For the before part, that should have been taken care of by the CLI.
I saw you are setting the 'dist' folder to the language folders. This seems Ok to me, but did angular set an 'base-href' in there? It should be /
in that case. If the base/href in those folders is for example /uk/
, there might be an issue.
@SanderElias If you're building your angular project with the --localize flag, angular automatically builds a separate project for each language which is defined in your angular.json file. Angular builds the project for each language into a subfolder with a two letter locale string (e.g en, de, it, pl) and also sets the baseHref for each project to this two letter locale. Also tried out your plugin but actually it doesn't work as expected for us.
I think this should be implemented directly in the scully core and not as a plugin. During the scully build, scully should detect if a localize settings exists in the angular.json file, and then also recognize that the dist folder have multiple subfolders for each language and then scully should automatically build the static sites for each languages.
Your baseHref plugin basically do the same as my own... The problem also is, when the baseHrefs are en, de or whatever (which is set automatically by angular cli), then scully cannot parse the content of the pages and the prerendered static pages are empty within the <app-root>
. I could fix this when i set the baseHref for each language in the angular.json file to "/" and then my/your basehref plugin sets the correct baseHref again for each page. But then we come to the next issue, all href links in the prerendered static pages not starting with /de/whatever/ or /en/whatever/, and are just /whatever/ and that's wrong. I now end up with another plugin which fixes all links in tags, and all looks fine for me.
const {registerPlugin} = require('@scullyio/scully');
const fixStaticLinksPlugin = async (html) => {
const regex = new RegExp('(<a[^>]* href="\/)([^"]*)"', 'gmi');
html = html.replace(regex, `$1${process.env.LOCALE}/$2"`);
return Promise.resolve(html);
};
registerPlugin('render', 'fixStaticLinks', fixStaticLinksPlugin);
module.exports.fixStaticLinksPlugin = fixStaticLinksPlugin;
Goal Deliverable: 2020-07-16
I'm sorry for responding to an already closed issue. I have read through this thread but I'm not 100% sure if I see the solution. Is it the combination of using the the base-href-rewrite
plugin and the RegEx by @dyingangel666?
I'm having the same problem where I'm using Angular's i18n
, get two folders when doing a build and running Scully doesn't exactly give me the right result. I have tried the above solutions but I end up getting one single static folder with the last language in my list to be the one that get statically generated. I'd love to have a walkthrough of what are the right steps to fix this particular issue. (In particular, how the angular.json
file is setup, how the baseHref
is setup [if it's setup via APP_BASE_HREF
], what the Scully config looks like and what is the command that needs to be executed. I think I'm close to getting this to work, I just need one last thing :)
@tpiros Ok let's sumarize all things from my working project:
The package.json with some build stuff:
{
"name": "marketplace-frontend",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "npm run getproducts; ng serve --host 0.0.0.0",
"start:noupdate": "ng serve --host 0.0.0.0 --port 4201",
"build": "npm run clear:dist; npm run getproducts; ng build --prod --localize --stats-json; env SET_PUPPETEER_EXECUTABLE_PATH=true npm run scully:de; npm run scully:en; gzipper compress --brotli --include js,css,html --level 6 ./dist/static;",
"buildLocal": "npm run clear:dist; npm run getproducts; ng build --prod --localize --stats-json; env SET_PUPPETEER_EXECUTABLE_PATH=false npm run scully:de; npm run scully:en; gzipper compress --brotli --include js,css,html --level 6 ./dist/static;",
"buildLocal:noupdate": "ng build --prod --localize --stats-json; env SET_PUPPETEER_EXECUTABLE_PATH=false npm run scully:de; npm run scully:en",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"clear:dist": "npx rimraf ./dist",
"copyfiles": "copy-files-from-to --when-file-exists overwrite",
"prepareproducts": "node product-data-preprocessor.js",
"getproducts:de": "npx mkdirp ./dist/marketplace-frontend/de/assets; curl -m 900 -o ./dist/marketplace-frontend/de/assets/products.json https://app.softgarden.io/api/rest/backend/v3/marketplace/de",
"getproducts:en": "npx mkdirp ./dist/marketplace-frontend/en/assets; curl -m 900 -o ./dist/marketplace-frontend/en/assets/products.json https://app.softgarden.io/api/rest/backend/v3/marketplace/en",
"getproducts": "npm run getproducts:de; npm run getproducts:en; npm run prepareproducts; npm run copyfiles",
"scully:de": "env URLPREFIX=https://marketplace.softgarden.io env LOCALE=de scully --scanRoutes",
"scully:en": "env URLPREFIX=https://marketplace.softgarden.io env LOCALE=en scully --scanRoutes",
"scully:serve": "scully serve",
"i18n": "ng xi18n --format=xlf --output-path=src/locales --out-file=messages.xlf",
"xliffmerge": "ng run marketplace-frontend:xliffmerge",
"translate": "npm run i18n; npm run xliffmerge",
"local": "docker-compose down; docker-compose pull; docker-compose up --build"
},
"copyFiles": [
{
"from": "dist/marketplace-frontend/de/assets/products.json",
"to": "src/assets/products.json"
},
{
"from": "./src/root/*",
"to": "./dist/static/"
}
],
"private": true,
"dependencies": {
"@angular/animations": "10.2.1",
"@angular/cdk": "10.2.7",
"@angular/common": "10.2.1",
"@angular/compiler": "10.2.1",
"@angular/core": "10.2.1",
"@angular/forms": "10.2.1",
"@angular/localize": "10.2.1",
"@angular/platform-browser": "10.2.1",
"@angular/platform-browser-dynamic": "10.2.1",
"@angular/router": "10.2.1",
"@scullyio/init": "1.0.1",
"@scullyio/ng-lib": "1.0.0",
"@scullyio/scully": "1.0.4",
"lazysizes": "5.2.1",
"new-event-polyfill": "1.0.1",
"normalize.css": "8.0.1",
"rxjs": "6.5.4",
"tslib": "1.10.0",
"zone.js": "0.10.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "0.1002.0",
"@angular/cli": "10.2.0",
"@angular/compiler-cli": "10.2.1",
"@angular/language-service": "10.2.1",
"@ngx-i18nsupport/ngx-i18nsupport": "1.1.6",
"@ngx-i18nsupport/tooling": "8.0.3",
"@scullyio/scully-plugin-base-href-rewrite": "0.0.2",
"@types/jasmine": "~3.5.0",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1",
"codelyzer": "5.2.1",
"copy-files-from-to": "3.2.0",
"gzipper": "^4.3.0",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~5.0.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.5.0",
"image-downloader": "4.0.1",
"imagemin": "7.0.1",
"imagemin-mozjpeg": "9.0.0",
"imagemin-pngquant": "9.0.1",
"protractor": "5.4.3",
"resize-img": "2.0.0",
"rimraf": "3.0.2",
"scully-plugin-minify-html": "3.1.2",
"ts-node": "~8.3.0",
"tslint": "~6.1.0",
"typescript": "~4.0.2",
"update-json-file": "1.1.1"
}
}
Then the scully config (ts version):
import {ScullyConfig, setPluginConfig} from '@scullyio/scully';
import {MinifyHtml} from 'scully-plugin-minify-html';
import {baseHrefRewrite} from '@scullyio/scully-plugin-base-href-rewrite';
require('./postrender-plugins/fixStaticLinks');
require('./postrender-plugins/sitemapGenerator');
// @ts-ignore
setPluginConfig(baseHrefRewrite, {href: `/${process.env.LOCALE}/`});
export const config: ScullyConfig = {
projectRoot: './src',
defaultPostRenderers: [
'seoHrefOptimise',
'sitemapGenerator',
'fixStaticLinks',
// @ts-ignore
baseHrefRewrite,
MinifyHtml,
],
inlineStateOnly: true,
projectName: 'marketplace-frontend',
outDir: `./dist/static/${process.env.LOCALE}`,
distFolder: `./dist/marketplace-frontend/${process.env.LOCALE}`,
reloadPort: 4200,
staticPort: 1668,
routes: {
'/:productId': {
type: 'json',
productId: {
url: 'http://localhost:1668/assets/products.json',
property: 'id'
}
}
},
puppeteerLaunchOptions: {
executablePath: process.env.PUPPETEER_EXECUTABLE_PATH ? 'google-chrome-stable' : '',
args: ['--no-sandbox', '--disable-setuid-sandbox']
}
};
And finally the angular.json:
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"marketplace-frontend": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"i18n": {
"sourceLocale": {
"code": "de",
"baseHref": "/"
},
"locales": {
"en": {
"translation": "src/locales/messages.en.xlf",
"baseHref": "/"
}
}
},
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/marketplace-frontend",
"resourcesOutputPath": "assets/fonts",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": [],
"stylePreprocessorOptions": {
"includePaths": [
"src/app"
]
}
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"assets": [
{ "glob": "**/*", "input": "src/assets/", "ignore": ["products.json"], "output": "/assets/" }
],
"deleteOutputPath": false,
"optimization": true,
"outputHashing": "bundles",
"sourceMap": false,
"extractCss": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "marketplace-frontend:build"
},
"configurations": {
"production": {
"browserTarget": "marketplace-frontend:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "marketplace-frontend:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"xliffmerge": {
"builder": "@ngx-i18nsupport/tooling:xliffmerge",
"options": {
"xliffmergeOptions": {
"srcDir": "src/locales",
"genDir": "src/locales",
"i18nFile": "messages.xlf",
"i18nBaseFile": "messages",
"i18nFormat": "xlf",
"encoding": "UTF-8",
"defaultLanguage": "de",
"languages": [
"en"
],
"removeUnusedIds": true,
"supportNgxTranslate": false,
"ngxTranslateExtractionPattern": "@@|ngx-translate",
"useSourceAsTarget": true,
"targetPraefix": "",
"targetSuffix": "",
"beautifyOutput": true,
"allowIdChange": false,
"autotranslate": false,
"apikey": "",
"apikeyfile": "",
"verbose": false,
"quiet": false
}
}
}
}
}
},
"defaultProject": "marketplace-frontend"
}
And here the code for my fixStaticLinks.js file:
const {registerPlugin} = require('@scullyio/scully');
const fixStaticLinksPlugin = async (html) => {
const regex = new RegExp('(<a[^>]* href="\/)([^"]*)"', 'gmi');
html = html.replace(regex, `$1${process.env.LOCALE}/$2"`);
return Promise.resolve(html);
};
registerPlugin('render', 'fixStaticLinks', fixStaticLinksPlugin);
module.exports.fixStaticLinksPlugin = fixStaticLinksPlugin;
Thank you @dyingangel666! I found what was missing at my end ... it was the pesky seoHrefOptimise
renderer. I didn't notice that I was missing that up until now ... 🙄 thank you again!
Just curious @dyingangel666 (and if you're on some Slack or Discord channel where we can converse, let me know) but, does your Scully command "hang"? I get the routes generated and everything seem to be working fine except in scully.log
I get Received Kill command
and the process hangs for about 1-2 minutes and after it just quits. Not sure why this is but I'm not getting the same behaviour with non i18n projects.
@tpiros Mh nope in my project everything is working and running successfully... Can you post the complete error log?
@dyingangel666 oddly enough, it turned out to be a process that got "stuck". For reasons unknown, the ScullyServer
process didn't shut down and was running and while I started it again, it would just keep on crashing. Good 'ol pkill -9 ScullyServer
did the job ...
hi @dyingangel666 - one question. When you deployed your project, did you ever run into an issue where only one language would get pre-rendered and the other wouldn't? I'm having some funky issues when deploying to Amplify - one language doesn't pre-render the other does. Tt's almost like whatever I put in as the second export LANG=xx && npm run scully
bit wins.
@tpiros Mhhh nope no issues like that in my project. All languages successfully built in their respective subfolders... Was the default angular project built successfully with all languages and just within the scully build something goes wrong?
I'm trying to debug that. When deploying to Amplify, I need to run npm run scully
once with one language in order to get pre-rendering. so the build script looks like this now:
"scully:en": "export LOCALE=en && npm run scully",
"scully:es": "export LOCALE=es && npm run scully",
"static": "ng build --prod --localize; npm run scully:en; npm run scully:en; npm run scully:es"
I'm running some tests - not sure what has gone wrong ... :(
Mhhh did you also tried to run the commands sequentially with &&:
ng build --prod --localize && npm run scully:en && npm run scully:en && npm run scully:es
Not sure if it makes a difference... but it's worth a try. Can you show me all npm scripts?
yes, that was the original, didn't make a difference. (theoretically ;
runs the script regardless of the success of the previous one, whereas &&
only runs if the previous is successful)
This is the version that doesn't work. The EN site is empty the articles only load when JS is enabled, the ES site works both ways since the content is pre-rendered.
I have a feeling it has to do with my implementation of the service that gets this data, because I've done a test with a simpler API and that seems to be working just fine. FYI I'm using Storyblok as my CMS where I'm fetching the data from.
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"scully": "scully",
"scully:serve": "scully serve",
"scully:en": "export LOCALE=en && npm run scully",
"scully:es": "export LOCALE=es && npm run scully",
"static": "ng build --prod --localize; npm run scully:en; npm run scully:es"
},
Found the culprit! It's the Storyblok JS client ... not sure why it works if I run scully 3x and why it doesn't work if I run it just twice...I'll talk to their devs and try to figure it out. What bugs me is that I don't see a difference between my local environment and Amplify.
🧩 Feature request
Description
Angular 9 allows building the app like
ng build --localize
to enable localization. In previous versions of anular a separate build for locale was needed but output was similar. Angular 9 allows to specify locales for i18n in angular.json in a following way:Building angular with
--localize
then results in following dist structure:./dist/{project-name}/{locale-id}
. Scully is not possible to configure for this case at the moment. Scully checks only./dist/{project-name}
by default. Besides that scully does not seem to have a mechanism to tell it about baseHref that project has from a config file. Here is example of the dist structure:Describe the solution you'd like
There a couple of options we could have here:
outDir: './dist/static'
it would do the following:./dist/static/{locale-id}
. Scully should be able to respect baseHref in this case (we can provide it in config file or maybe scully can read it fromangular.json
), but there can be other use cases when users might manually set base href inindex.html
.Describe alternatives you've considered
Currently this behaviour is possible to achieve in combination of using `distFolder` and `outDir` settings in `scully.config.js` and `--baseFilter` option in CLI command (although naming of this argument is not clear what its intension is, maybe it is just a happy coincidence that it works). Here is an example config: ``` exports.config = { projectRoot: './', outDir: './dist/static/en', distFolder: './dist/frontend/en', routes: {}, puppeteerLaunchOptions: { args: ['--no-sandbox', '--disable-setuid-sandbox'], }, }; ``` which if ran with `npm run scully -- --bf /en` could give a desired result, but I believe this can get really messy when projects will have more locales (in my case I have 3). It is also possible to further improve the situation using `process.env`: ``` exports.config = { projectRoot: './', outDir: `./dist/static/${process.env.LOCALE}`, distFolder: `./dist/frontend/${process.env.LOCALE}`, routes: {}, puppeteerLaunchOptions: { args: ['--no-sandbox', '--disable-setuid-sandbox'], }, }; ``` which can then be executed like: `export LOCALE=en && npm run scully --bf /$LOCALE` This is then cleaner and does not require a config file per locale, but does require running scully once per locale. Delivery Goal - 07/16/2020