Merge pull request #96 from locomotivemtl/mcaskill-refactor-build-options
This commit is contained in:
@@ -9,6 +9,8 @@ import { basename } from 'node:path';
|
|||||||
/**
|
/**
|
||||||
* Concatenates groups of files.
|
* Concatenates groups of files.
|
||||||
*
|
*
|
||||||
|
* @todo Add support for minification.
|
||||||
|
*
|
||||||
* @async
|
* @async
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,13 +5,54 @@ import template from '../utils/template.js';
|
|||||||
import esbuild from 'esbuild';
|
import esbuild from 'esbuild';
|
||||||
import { basename } from 'node:path';
|
import { basename } from 'node:path';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const {object} defaultESBuildOptions - The default shared ESBuild options.
|
||||||
|
* @const {object} developmentESBuildOptions - The predefined ESBuild options for development.
|
||||||
|
* @const {object} productionESBuildOptions - The predefined ESBuild options for production.
|
||||||
|
*/
|
||||||
|
export const defaultESBuildOptions = {
|
||||||
|
bundle: true,
|
||||||
|
color: true,
|
||||||
|
sourcemap: true,
|
||||||
|
target: [
|
||||||
|
'es2015',
|
||||||
|
],
|
||||||
|
};
|
||||||
|
export const developmentESBuildOptions = Object.assign({}, defaultESBuildOptions);
|
||||||
|
export const productionESBuildOptions = Object.assign({}, defaultESBuildOptions, {
|
||||||
|
logLevel: 'warning',
|
||||||
|
minify: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const {object} developmentScriptsArgs - The predefined `compileScripts()` options for development.
|
||||||
|
* @const {object} productionScriptsArgs - The predefined `compileScripts()` options for production.
|
||||||
|
*/
|
||||||
|
export const developmentScriptsArgs = [
|
||||||
|
developmentESBuildOptions,
|
||||||
|
];
|
||||||
|
export const productionScriptsArgs = [
|
||||||
|
productionESBuildOptions,
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bundles and minifies main JavaScript files.
|
* Bundles and minifies main JavaScript files.
|
||||||
*
|
*
|
||||||
* @async
|
* @async
|
||||||
|
* @param {object} [esBuildOptions=null] - Customize the ESBuild build API options.
|
||||||
|
* If `null`, default production options are used.
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
export default async function compileScripts() {
|
export default async function compileScripts(esBuildOptions = null) {
|
||||||
|
if (esBuildOptions == null) {
|
||||||
|
esBuildOptions = productionESBuildOptions;
|
||||||
|
} else if (
|
||||||
|
esBuildOptions !== developmentESBuildOptions &&
|
||||||
|
esBuildOptions !== productionESBuildOptions
|
||||||
|
) {
|
||||||
|
esBuildOptions = Object.assign({}, defaultESBuildOptions, esBuildOptions);
|
||||||
|
}
|
||||||
|
|
||||||
loconfig.tasks.scripts.forEach(async ({
|
loconfig.tasks.scripts.forEach(async ({
|
||||||
includes,
|
includes,
|
||||||
outdir = '',
|
outdir = '',
|
||||||
@@ -35,19 +76,11 @@ export default async function compileScripts() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await esbuild.build({
|
await esbuild.build(Object.assign({}, esBuildOptions, {
|
||||||
entryPoints: includes,
|
entryPoints: includes,
|
||||||
bundle: true,
|
|
||||||
minify: true,
|
|
||||||
sourcemap: true,
|
|
||||||
color: true,
|
|
||||||
logLevel: 'error',
|
|
||||||
target: [
|
|
||||||
'es2015',
|
|
||||||
],
|
|
||||||
outdir,
|
outdir,
|
||||||
outfile
|
outfile,
|
||||||
});
|
}));
|
||||||
|
|
||||||
message(`${filename} compiled`, 'success', timeLabel);
|
message(`${filename} compiled`, 'success', timeLabel);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import loconfig from '../../loconfig.json';
|
import loconfig from '../../loconfig.json';
|
||||||
import message from '../utils/message.js';
|
import message from '../utils/message.js';
|
||||||
import notification from '../utils/notification.js';
|
import notification from '../utils/notification.js';
|
||||||
import postcss from '../utils/postcss.js';
|
import postcss, { pluginsMap as postcssPluginsMap } from '../utils/postcss.js';
|
||||||
import template from '../utils/template.js';
|
import template from '../utils/template.js';
|
||||||
import { writeFile } from 'node:fs/promises';
|
import { writeFile } from 'node:fs/promises';
|
||||||
import { basename } from 'node:path';
|
import { basename } from 'node:path';
|
||||||
@@ -10,13 +10,91 @@ import sass from 'node-sass';
|
|||||||
|
|
||||||
const sassRender = promisify(sass.render);
|
const sassRender = promisify(sass.render);
|
||||||
|
|
||||||
|
let postcssProcessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const {object} defaultSassOptions - The default shared Sass options.
|
||||||
|
* @const {object} developmentSassOptions - The predefined Sass options for development.
|
||||||
|
* @const {object} productionSassOptions - The predefined Sass options for production.
|
||||||
|
*/
|
||||||
|
export const defaultSassOptions = {
|
||||||
|
omitSourceMapUrl: true,
|
||||||
|
sourceMap: true,
|
||||||
|
sourceMapContents: true,
|
||||||
|
};
|
||||||
|
export const developmentSassOptions = Object.assign({}, defaultSassOptions, {
|
||||||
|
outputStyle: 'expanded',
|
||||||
|
});
|
||||||
|
export const productionSassOptions = Object.assign({}, defaultSassOptions, {
|
||||||
|
outputStyle: 'compressed',
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const {object} defaultPostCSSOptions - The default shared PostCSS options.
|
||||||
|
* @const {object} developmentPostCSSOptions - The predefined PostCSS options for development.
|
||||||
|
* @const {object} productionPostCSSOptions - The predefined PostCSS options for production.
|
||||||
|
*/
|
||||||
|
export const defaultPostCSSOptions = {
|
||||||
|
processor: {
|
||||||
|
map: {
|
||||||
|
annotation: false,
|
||||||
|
inline: false,
|
||||||
|
sourcesContent: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export const developmentPostCSSOptions = Object.assign({}, defaultPostCSSOptions);
|
||||||
|
export const productionPostCSSOptions = Object.assign({}, defaultPostCSSOptions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const {object} developmentStylesArgs - The predefined `compileStyles()` options for development.
|
||||||
|
* @const {object} productionStylesArgs - The predefined `compileStyles()` options for production.
|
||||||
|
*/
|
||||||
|
export const developmentStylesArgs = [
|
||||||
|
developmentSassOptions,
|
||||||
|
developmentPostCSSOptions,
|
||||||
|
];
|
||||||
|
export const productionStylesArgs = [
|
||||||
|
productionSassOptions,
|
||||||
|
productionPostCSSOptions,
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiles and minifies main Sass files to CSS.
|
* Compiles and minifies main Sass files to CSS.
|
||||||
*
|
*
|
||||||
|
* @todo Add deep merge of `postcssOptions` to better support customization
|
||||||
|
* of default processor options.
|
||||||
|
*
|
||||||
* @async
|
* @async
|
||||||
|
* @param {object} [sassOptions=null] - Customize the Sass render API options.
|
||||||
|
* If `null`, default production options are used.
|
||||||
|
* @param {object|boolean} [postcssOptions=null] - Customize the PostCSS processor API options.
|
||||||
|
* If `null`, default production options are used.
|
||||||
|
* If `false`, PostCSS processing will be ignored.
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
export default async function compileStyles() {
|
export default async function compileStyles(sassOptions = null, postcssOptions = null) {
|
||||||
|
if (sassOptions == null) {
|
||||||
|
sassOptions = productionSassOptions;
|
||||||
|
} else if (
|
||||||
|
sassOptions !== developmentSassOptions &&
|
||||||
|
sassOptions !== productionSassOptions
|
||||||
|
) {
|
||||||
|
sassOptions = Object.assign({}, defaultSassOptions, sassOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (postcss) {
|
||||||
|
if (postcssOptions == null) {
|
||||||
|
postcssOptions = productionPostCSSOptions;
|
||||||
|
} else if (
|
||||||
|
postcssOptions !== false &&
|
||||||
|
postcssOptions !== developmentSassOptions &&
|
||||||
|
postcssOptions !== productionSassOptions
|
||||||
|
) {
|
||||||
|
postcssOptions = Object.assign({}, defaultPostCSSOptions, postcssOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loconfig.tasks.styles.forEach(async ({
|
loconfig.tasks.styles.forEach(async ({
|
||||||
infile,
|
infile,
|
||||||
outfile
|
outfile
|
||||||
@@ -30,25 +108,26 @@ export default async function compileStyles() {
|
|||||||
infile = template(infile);
|
infile = template(infile);
|
||||||
outfile = template(outfile);
|
outfile = template(outfile);
|
||||||
|
|
||||||
let result = await sassRender({
|
let result = await sassRender(Object.assign({}, sassOptions, {
|
||||||
file: infile,
|
file: infile,
|
||||||
omitSourceMapUrl: true,
|
|
||||||
outFile: outfile,
|
outFile: outfile,
|
||||||
outputStyle: 'compressed',
|
}));
|
||||||
sourceMap: true,
|
|
||||||
sourceMapContents: true
|
|
||||||
});
|
|
||||||
|
|
||||||
if (postcss) {
|
if (postcss && postcssOptions) {
|
||||||
result = await postcss.process(result.css, {
|
if (typeof postcssProcessor === 'undefined') {
|
||||||
|
postcssProcessor = createPostCSSProcessor(
|
||||||
|
postcssPluginsMap,
|
||||||
|
postcssOptions
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = await postcssProcessor.process(
|
||||||
|
result.css,
|
||||||
|
Object.assign({}, postcssOptions.processor, {
|
||||||
from: outfile,
|
from: outfile,
|
||||||
to: outfile,
|
to: outfile,
|
||||||
map: {
|
})
|
||||||
annotation: false,
|
);
|
||||||
inline: false,
|
|
||||||
sourcesContent: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.warnings) {
|
if (result.warnings) {
|
||||||
const warnings = result.warnings();
|
const warnings = result.warnings();
|
||||||
@@ -103,3 +182,32 @@ export default async function compileStyles() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a PostCSS Processor with the given plugins and options.
|
||||||
|
*
|
||||||
|
* @param {array<(function|object)>|object<string, (function|object)>} pluginsListOrMap -
|
||||||
|
* A list or map of plugins.
|
||||||
|
* If a map of plugins, the plugin name looks up `options`.
|
||||||
|
* @param {object} options - The PostCSS options.
|
||||||
|
*/
|
||||||
|
function createPostCSSProcessor(pluginsListOrMap, options)
|
||||||
|
{
|
||||||
|
let plugins;
|
||||||
|
|
||||||
|
if (Array.isArray(pluginsListOrMap)) {
|
||||||
|
plugins = pluginsListOrMap;
|
||||||
|
} else {
|
||||||
|
plugins = [];
|
||||||
|
|
||||||
|
for (let [ name, plugin ] of Object.entries(pluginsListOrMap)) {
|
||||||
|
if (name in options) {
|
||||||
|
plugin = plugin[name](options[name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins.push(plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return postcss(plugins);
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,13 +5,48 @@ import template from '../utils/template.js';
|
|||||||
import { basename } from 'node:path';
|
import { basename } from 'node:path';
|
||||||
import mixer from 'svg-mixer';
|
import mixer from 'svg-mixer';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const {object} defaultMixerOptions - The default shared Mixer options.
|
||||||
|
* @const {object} developmentMixerOptions - The predefined Mixer options for development.
|
||||||
|
* @const {object} productionMixerOptions - The predefined Mixer options for production.
|
||||||
|
*/
|
||||||
|
export const defaultMixerOptions = {
|
||||||
|
spriteConfig: {
|
||||||
|
usages: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export const developmentMixerOptions = Object.assign({}, defaultMixerOptions);
|
||||||
|
export const productionMixerOptions = Object.assign({}, defaultMixerOptions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const {object} developmentSVGsArgs - The predefined `compileSVGs()` options for development.
|
||||||
|
* @const {object} productionSVGsArgs - The predefined `compileSVGs()` options for production.
|
||||||
|
*/
|
||||||
|
export const developmentSVGsArgs = [
|
||||||
|
developmentMixerOptions,
|
||||||
|
];
|
||||||
|
export const productionSVGsArgs = [
|
||||||
|
productionMixerOptions,
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates and transforms SVG spritesheets.
|
* Generates and transforms SVG spritesheets.
|
||||||
*
|
*
|
||||||
* @async
|
* @async
|
||||||
|
* @param {object} [mixerOptions=null] - Customize the Mixer API options.
|
||||||
|
* If `null`, default production options are used.
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
export default async function compileSVGs() {
|
export default async function compileSVGs(mixerOptions = null) {
|
||||||
|
if (mixerOptions == null) {
|
||||||
|
mixerOptions = productionMixerOptions;
|
||||||
|
} else if (
|
||||||
|
mixerOptions !== developmentMixerOptions &&
|
||||||
|
mixerOptions !== productionMixerOptions
|
||||||
|
) {
|
||||||
|
mixerOptions = Object.assign({}, defaultMixerOptions, mixerOptions);
|
||||||
|
}
|
||||||
|
|
||||||
loconfig.tasks.svgs.forEach(async ({
|
loconfig.tasks.svgs.forEach(async ({
|
||||||
includes,
|
includes,
|
||||||
outfile
|
outfile
|
||||||
@@ -25,11 +60,7 @@ export default async function compileSVGs() {
|
|||||||
includes = includes.map((path) => template(path));
|
includes = includes.map((path) => template(path));
|
||||||
outfile = template(outfile);
|
outfile = template(outfile);
|
||||||
|
|
||||||
const result = await mixer(includes, {
|
const result = await mixer(includes, mixerOptions);
|
||||||
spriteConfig: {
|
|
||||||
usages: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await result.write(outfile);
|
await result.write(outfile);
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,28 @@
|
|||||||
/**
|
/**
|
||||||
* @file If available, returns the PostCSS processor with any plugins.
|
* @file If available, returns the PostCSS Processor creator and
|
||||||
|
* any the Autoprefixer PostCSS plugin.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
try {
|
let postcss, autoprefixer;
|
||||||
var { default: postcss } = await import('postcss');
|
|
||||||
let { default: autoprefixer } = await import('autoprefixer');
|
|
||||||
|
|
||||||
postcss = postcss([ autoprefixer ]);
|
try {
|
||||||
|
postcss = await import('postcss');
|
||||||
|
postcss = postcss.default;
|
||||||
|
|
||||||
|
autoprefixer = await import('autoprefixer');
|
||||||
|
autoprefixer = autoprefixer.default;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
postcss = null;
|
postcss = null;
|
||||||
|
autoprefixer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default postcss;
|
export default postcss;
|
||||||
|
export const pluginsList = [
|
||||||
|
autoprefixer,
|
||||||
|
];
|
||||||
|
export const pluginsMap = {
|
||||||
|
'autoprefixer': autoprefixer,
|
||||||
|
};
|
||||||
|
export {
|
||||||
|
autoprefixer
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import loconfig from '../loconfig.json';
|
import loconfig from '../loconfig.json';
|
||||||
import concatFiles from './tasks/concats.js';
|
import concatFiles from './tasks/concats.js';
|
||||||
import compileScripts from './tasks/scripts.js';
|
import compileScripts, { developmentScriptsArgs } from './tasks/scripts.js';
|
||||||
import compileStyles from './tasks/styles.js' ;
|
import compileStyles, { developmentStylesArgs } from './tasks/styles.js' ;
|
||||||
import compileSVGs from './tasks/svgs.js';
|
import compileSVGs, { developmentSVGsArgs } from './tasks/svgs.js';
|
||||||
import template from './utils/template.js';
|
import template from './utils/template.js';
|
||||||
import server from 'browser-sync';
|
import server from 'browser-sync';
|
||||||
import { join } from 'node:path';
|
import { join } from 'node:path';
|
||||||
@@ -30,9 +30,9 @@ server.init(serverConfig);
|
|||||||
// Build scripts, compile styles, concat files,
|
// Build scripts, compile styles, concat files,
|
||||||
// and generate spritesheets on first hit
|
// and generate spritesheets on first hit
|
||||||
concatFiles();
|
concatFiles();
|
||||||
compileScripts();
|
compileScripts(...developmentScriptsArgs);
|
||||||
compileStyles();
|
compileStyles(...developmentStylesArgs);
|
||||||
compileSVGs();
|
compileSVGs(...developmentSVGsArgs);
|
||||||
|
|
||||||
// and call any methods on it.
|
// and call any methods on it.
|
||||||
server.watch(
|
server.watch(
|
||||||
@@ -50,7 +50,7 @@ server.watch(
|
|||||||
join(paths.scripts.src, '**/*.js'),
|
join(paths.scripts.src, '**/*.js'),
|
||||||
]
|
]
|
||||||
).on('change', () => {
|
).on('change', () => {
|
||||||
compileScripts();
|
compileScripts(...developmentScriptsArgs);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Watch concats
|
// Watch concats
|
||||||
@@ -69,7 +69,7 @@ server.watch(
|
|||||||
join(paths.styles.src, '**/*.scss'),
|
join(paths.styles.src, '**/*.scss'),
|
||||||
]
|
]
|
||||||
).on('change', () => {
|
).on('change', () => {
|
||||||
compileStyles();
|
compileStyles(...developmentStylesArgs);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Watch svgs
|
// Watch svgs
|
||||||
@@ -78,5 +78,5 @@ server.watch(
|
|||||||
join(paths.svgs.src, '*.svg'),
|
join(paths.svgs.src, '*.svg'),
|
||||||
]
|
]
|
||||||
).on('change', () => {
|
).on('change', () => {
|
||||||
compileSVGs();
|
compileSVGs(...developmentSVGsArgs);
|
||||||
});
|
});
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user