From 86f88c3f147b9afc9f7ed35b9a437e04354352b9 Mon Sep 17 00:00:00 2001 From: Chauncey McAskill Date: Tue, 22 Mar 2022 16:10:18 -0400 Subject: [PATCH] Refactor watch.js Switched to BrowserSync's recommended post-2.0.0 syntax. Organized logic into functions for easier reading. Add support for customizing the BrowserSync server from 'loconfig.json'. Example: ```json "server": { "open": true, "https": { "key": "~/.config/valet/Certificates/{% paths.url %}.key", "cert": "~/.config/valet/Certificates/{% paths.url %}.crt" } } ``` --- build/watch.js | 215 +++++++++++++++++++++++++++++++------------------ 1 file changed, 136 insertions(+), 79 deletions(-) diff --git a/build/watch.js b/build/watch.js index d1b9086..d6d4f6d 100644 --- a/build/watch.js +++ b/build/watch.js @@ -3,46 +3,12 @@ import concatFiles, { developmentConcatFilesArgs } from './tasks/concats.js'; import compileScripts, { developmentScriptsArgs } from './tasks/scripts.js'; import compileStyles, { developmentStylesArgs } from './tasks/styles.js' ; import compileSVGs, { developmentSVGsArgs } from './tasks/svgs.js'; +import message from './utils/message.js'; +import notification from './utils/notification.js'; import resolve from './utils/template.js'; -import server from 'browser-sync'; +import browserSync from 'browser-sync'; import { join } from 'node:path'; -const { paths, tasks } = loconfig; - -// Convert view(s) to an array -switch (typeof paths.views) { - case 'string': - paths.views = [ paths.views ]; - break; - - case 'object': - if (paths.views == null) { - paths.views = []; - } else if (!Array.isArray(paths.views)) { - paths.views = Object.values(paths.views); - } - break; -} - -const serverConfig = { - open: false, - notify: false -}; - -// Resolve the URI for the Browsersync server -if (typeof paths.url === 'string' && paths.url.length > 0) { - // Use proxy - serverConfig.proxy = paths.url; -} else { - // Use base directory - serverConfig.server = { - baseDir: paths.dest - }; -} - -// Start the Browsersync server -server.init(serverConfig); - // Build scripts, compile styles, concat files, // and generate spritesheets on first hit concatFiles(...developmentConcatFilesArgs); @@ -50,51 +16,142 @@ compileScripts(...developmentScriptsArgs); compileStyles(...developmentStylesArgs); compileSVGs(...developmentSVGsArgs); -// Reload on any changes to views or processed files -server.watch( - [ - ...paths.views, - join(paths.scripts.dest, '*.js'), - join(paths.styles.dest, '*.css'), - join(paths.svgs.dest, '*.svg'), - ] -).on('change', server.reload); +// Create a new BrowserSync instance +const server = browserSync.create(); -// Watch source scripts -server.watch( - [ - join(paths.scripts.src, '**/*.js'), - ] -).on('change', () => { - compileScripts(...developmentScriptsArgs); +// Start the BrowserSync server +server.init(createServerOptions(loconfig), (err) => { + if (err) { + message('Error starting development server', 'error'); + message(err); + + notification({ + title: 'Development server failed', + message: `${err.name}: ${err.message}` + }); + } }); -// Watch source concats -server.watch( - resolve( - tasks.concats.reduce( - (patterns, { includes }) => patterns.concat(includes), - [] +configureServer(server, loconfig); + +/** + * Configures the BrowserSync options. + * + * @param {BrowserSync} server - The BrowserSync API. + * @param {object} loconfig - The project configset. + * @param {object} loconfig.paths - The paths options. + * @param {object} loconfig.tasks - The tasks options. + * @return {void} + */ +function configureServer(server, { paths, tasks }) { + const views = createViewsArray(paths.views); + + // Reload on any changes to views or processed files + server.watch( + [ + ...views, + join(paths.scripts.dest, '*.js'), + join(paths.styles.dest, '*.css'), + join(paths.svgs.dest, '*.svg'), + ] + ).on('change', server.reload); + + // Watch source scripts + server.watch( + [ + join(paths.scripts.src, '**/*.js'), + ] + ).on('change', () => { + compileScripts(...developmentScriptsArgs); + }); + + // Watch source concats + server.watch( + resolve( + tasks.concats.reduce( + (patterns, { includes }) => patterns.concat(includes), + [] + ) ) - ) -).on('change', () => { - concatFiles(...developmentConcatFilesArgs); -}); + ).on('change', () => { + concatFiles(...developmentConcatFilesArgs); + }); -// Watch source styles -server.watch( - [ - join(paths.styles.src, '**/*.scss'), - ] -).on('change', () => { - compileStyles(...developmentStylesArgs); -}); + // Watch source styles + server.watch( + [ + join(paths.styles.src, '**/*.scss'), + ] + ).on('change', () => { + compileStyles(...developmentStylesArgs); + }); -// Watch source SVGs -server.watch( - [ - join(paths.svgs.src, '*.svg'), - ] -).on('change', () => { - compileSVGs(...developmentSVGsArgs); -}); + // Watch source SVGs + server.watch( + [ + join(paths.svgs.src, '*.svg'), + ] + ).on('change', () => { + compileSVGs(...developmentSVGsArgs); + }); +} + +/** + * Creates a new object with all the BrowserSync options. + * + * @param {object} loconfig - The project configset. + * @param {object} loconfig.paths - The paths options. + * @param {object} loconfig.server - The server options. + * @return {object} Returns the server options. + */ +function createServerOptions({ + paths, + server: options +}) { + const config = { + open: false, + notify: false + }; + + // Resolve the URI for the BrowserSync server + if (typeof paths.url === 'string' && paths.url.length > 0) { + // Use proxy + config.proxy = paths.url; + } else if (typeof paths.dest === 'string' && paths.dest.length > 0) { + // Use base directory + config.server = { + baseDir: paths.dest + }; + } + + Object.assign(config, resolve(options)); + + return config; +} + +/** + * Creates a new array (shallow-copied) from the views configset. + * + * @param {*} views - The views configset. + * @throws {TypeError} If views is invalid. + * @return {array} Returns the views array. + */ +function createViewsArray(views) { + if (Array.isArray(views)) { + return Array.from(views); + } + + switch (typeof views) { + case 'string': + return [ views ]; + + case 'object': + if (views != null) { + return Object.values(views); + } + } + + throw new TypeError( + 'Expected \'views\' to be a string, array, or object' + ); +}