Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const path = require('path');
- const fs = require('fs');
- const cmdArgs = require('command-line-args');
- const workboxBuild = require('workbox-build');
- // This script file's absolute path
- const SCRIPT_PATH = __dirname;
- // Repository absolute path
- const ROOT_PATH = path.resolve(SCRIPT_PATH, '..');
- // Default absolute path for generated service worker files
- const OUTPUT_BASE_PATH = path.join('sites', 'site_template', 'sites', 'ASDA', 'library', 'static', 'default', 'ServiceWorker');
- // Arguments structure
- const OPTIONS_DEFINITION = [
- { name: 'exclude-dev', alias: 'D', type: Boolean },
- { name: 'exclude-stg', alias: 'S', type: Boolean },
- { name: 'exclude-prod', alias: 'P', type: Boolean },
- { name: 'exclude-dep', alias: 'd', type: Boolean },
- { name: 'exclude-old', alias: 'o', type: Boolean },
- { name: 'exclude-both', alias: 'b', type: Boolean },
- { name: 'exclude-uncached', alias: 'u', type: Boolean },
- { name: 'output-path', alias: 'p', type: String, defaultOption: true, defaultValue: '.' },
- { name: 'output-files', alias: 'f', type: String, defaultValue: 'sw-{env}-{ver}.js' },
- { name: 'help', alias: 'h', type: Boolean }
- ];
- main();
- /**
- * Main function of the script
- * @returns {void}
- */
- function main() {
- let options;
- try {
- try {
- options = cmdArgs(OPTIONS_DEFINITION);
- if (options['exclude-dev'] && options['exclude-stg'] && options['exclude-prod']) {
- options = null;
- throw new Error('At least one environment must be NOT excluded');
- }
- if (options['exclude-dep'] && options['exclude-old'] && options['exclude-both'] && options['exclude-uncached']) {
- options = null;
- throw new Error('At least one version must be NOT excluded');
- }
- } catch (e) {
- console.error('Invalid arguments (' + e.message + '). Use --help or -h for help.');
- }
- if (options && options['help']) {
- getHelpContent().then((data) => console.log(data));
- } else if (options) {
- generateAllServiceWorkers(
- !options['exclude-dev'],
- !options['exclude-stg'],
- !options['exclude-prod'],
- !options['exclude-dep'],
- !options['exclude-old'],
- !options['exclude-both'],
- !options['exclude-uncached'],
- path.resolve(ROOT_PATH, OUTPUT_BASE_PATH, options['output-path']),
- options['output-files']
- );
- }
- } catch (e) {
- console.error(e);
- }
- };
- /**
- * Gets the help (--help | -h) text from README.md
- * @returns {Promise} Resolves to README content or rejects with file operation error
- */
- function getHelpContent() {
- return new Promise(function(resolve, reject) {
- fs.readFile(path.resolve(SCRIPT_PATH, 'README.md'), 'utf8', (e, data) => {
- e ? reject(e) : resolve(data);
- });
- });
- }
- /**
- * Generates all service worker files.
- * @param {boolean} isDev Whether to generate 'dev' (Development) files
- * @param {boolean} isStg Whether to generate 'stg' (Staging) files
- * @param {boolean} isProd Whether to generate 'prod' (Production) files
- * @param {boolean} isDep Whether to generate 'dep' (DEP site) files
- * @param {boolean} isOld Whether to generate 'old' (Classic site) files
- * @param {boolean} isBoth Whether to generate 'both' (combined DEP and Classic) files
- * @param {boolean} isUncached Whether to generate 'nocache' (no pre-caching) files
- * @param {string} outputPath Destination directory (best use absolute path to avoid any relativity issues)
- * @returns {void}
- */
- function generateAllServiceWorkers(isDev, isStg, isProd, isDep, isOld, isBoth, isUncached, outputPath, filenameTemplate) {
- console.log('Generating service worker file(s) in:\n' + outputPath);
- let assetList = {
- 'main': path.resolve(SCRIPT_PATH, './blueprints/master-sw-blueprint.js'),
- 'dev': isDev ? path.resolve(SCRIPT_PATH, './blueprints/partials/dev-partial-sw-blueprint.js') : '',
- 'stg': isStg ? path.resolve(SCRIPT_PATH, './blueprints/partials/stg-partial-sw-blueprint.js') : '',
- 'prod': isProd ? path.resolve(SCRIPT_PATH, './blueprints/partials/prod-partial-sw-blueprint.js') : ''
- };
- let patternList = {
- 'dep': 'app_asda_react/cartridge/static/default/react/assets/**\/*.{js,css,svg}',
- 'old': 'app_asda_responsive/cartridge/static/default/responsive/**\/*.{mini.js,min.js,css,svg}'
- };
- let envList = [];
- isDev && envList.push('dev');
- isStg && envList.push('stg');
- isProd && envList.push('prod');
- let verList = [];
- isDep && verList.push('dep');
- isOld && verList.push('old');
- isBoth && verList.push('both');
- isUncached && verList.push('nocache');
- for (let envNum = 0; envNum < envList.length; envNum++) {
- for (let verNum = 0; verNum < verList.length; verNum++) {
- let env = envList[envNum];
- let ver = verList[verNum];
- let assets = [assetList['main'], assetList[env]];
- let patterns = [];
- let outputFile = filenameTemplate.replace('{env}', env).replace('{ver}', ver);
- (ver === 'dep' || ver === 'both') && patterns.push(patternList['dep']);
- (ver === 'old' || ver === 'both') && patterns.push(patternList['old']);
- generateServiceWorker(env, ver, assets, patterns, outputPath, outputFile);
- }
- }
- }
- /**
- * Generates a single Service Worker.
- * @param {string} environment Expected 'dev', 'stg', or 'Prod'
- * @param {string} version Expected 'dep', 'old', 'both', or 'nocache'
- * @param {Array} assets One or more strings with partial blueprint files
- * @param {Array} patterns Zero or more strings with precache file search patterns
- * @param {string} outputPath Directory where to create the service worker script
- * @returns {void}
- */
- function generateServiceWorker(environment, version, assets, patterns, outputPath, outputFile) {
- const tempBlueprintFile = path.resolve(SCRIPT_PATH, `temp-blueprint-${outputFile}`);
- const swFile = path.resolve(outputPath, outputFile);
- createBlueprint(assets[0], assets[1], tempBlueprintFile)
- .then(() => workboxBuild.injectManifest({
- swSrc: tempBlueprintFile,
- swDest: swFile,
- globDirectory: path.resolve(ROOT_PATH, 'cartridges'),
- globPatterns: patterns,
- globIgnores: ['**/critical.css'],
- manifestTransforms: [
- addPlaceholderPrefix,
- addOfflinePages
- ]
- }))
- .then(({count, size, warnings}) => {
- warnings.forEach((warn) => {
- console.warn(`${outputFile}:`, warn);
- });
- console.log(`${outputFile}: Included ${count} files for precache` + (!isNaN(size) ? ` (total ${size} bytes).` : ''));
- })
- .catch((e) => {
- console.error(`Error generating ${outputFile}:`, e);
- return Promise.resolve();
- })
- .then(() => {
- removeBlueprint(tempBlueprintFile)
- .catch((e) => {
- console.warn(`Could not delete ${tempBlueprintFile}. Please remove it manually.`);
- });
- });
- }
- /**
- * Creates a complete blueprint file (concatenates two partial blueprints into a temporary file)
- * @param {string} mainFile The master partial blueprint
- * @param {string} additionalFile The environment-dependent partial blueprint
- * @param {string} targetFile The destination temporary file
- * @returns {Promise} Resolved without a value or rejected with an error
- */
- function createBlueprint(mainFile, additionalFile, targetFile) {
- return new Promise(function(resolve, reject) {
- fs.copyFile(mainFile, targetFile, (e) => {
- if (e) {
- reject(e);
- } else {
- fs.readFile(additionalFile, (e, data) => {
- if (e) {
- reject(e);
- } else {
- fs.appendFile(targetFile, '\n\n' + data, 'utf8', (e) => {
- if (e) {
- reject(e);
- } else {
- resolve();
- }
- });
- }
- });
- }
- });
- });
- }
- /**
- * Deletes the temporary blueprint file
- * @param {string} targetFile The temporary file
- * @returns {Promise} Resolved without a value or rejected with an error
- */
- function removeBlueprint(targetFile) {
- return new Promise(function(resolve, reject) {
- fs.unlink(targetFile, (e) => {
- if (e) {
- reject(e);
- } else {
- resolve();
- }
- });
- resolve();
- });
- }
- /**
- * Removes "/.../default/" and "/v1523459585" from workbox manifest entries.
- * @param {array} originalEntries The manifest's precache list
- * @returns {object} Object with the modified precache entries and list of warnings
- */
- function addPlaceholderPrefix(originalEntries) {
- const entries = originalEntries.map((originalEntry) => {
- const entry = Object.assign({}, originalEntry);
- entry.url = entry.url
- .replace(/(^.+\/default\/)/gi, '') // Remove the base path "/.../default/"
- .replace(/\/v\d+/gi, ''); // Remove the "/v1523459585/" (DMW versioning) part
- return entry;
- });
- return {
- manifest: entries,
- warnings: []
- };
- }
- /**
- * Adds "/offline.html" for precaching to workbox manifest entries
- * @param {array} originalEntries The manifest's precache list
- * @returns {object} Object with the modified precache entries and list of warnings
- */
- function addOfflinePages(originalEntries) {
- const entries = originalEntries.slice();
- entries.push({
- 'url': '/offline.html',
- 'revision': 'v111111111111111111111111111111'
- });
- return {
- manifest: entries,
- warnings: []
- };
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement