All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Strict timestamp check to fallback image uploads and updated fallback upload step in deploy workflow
- Adjusted viewport settings to dynamically fix content height and add 20px bottom padding for fallback images
- Patched mini-sync to run on 127.0.0.1 and added option
portoption to baker config
- Updated manifest to correctly source assets in link tags, removing incorrect file references
- Fix fallback images generation
- Set
deviceScaleFactorto 2 for improved screenshot resolution.
- Added a fixed width (
FIXED_FALLBACK_SCREENSHOT_WIDTH) to generate mobile-friendly fallback screenshot images
- Added
screenshottask to baker for fallback image generation
- Removed
webHookUrlfrom baker.config
prepareCrosswalkdeprecated from baker config in favor of built-in crosswalk data handling.- Remove
staticAbsoluteBlock. All static assets use absolute paths now - Audio file (
.mp3) is now recognized byAssetsEngineand will be included in any hashing. - Extended Image files to include (
.webp,.avif). - Added
webHookUrloption in baker.config
- Added watcher for changes to
createPagestemplates - Updated dependencies
- Updated dependencies
- Added support for rending API endpoints in JSON, sitemaps.xml and robots.txt
- Added
createPagesto the test routine - Updated dependencies
- Updated dependencies
- Updated dependencies
- Refactored the package to comply with ES module standards
- Updated dependencies
- New
nunjucksVariablesconfig option to set global variables for all templates.
- Updated dependencies
- New
NOWglobal variable with the current timestamp returned bynew Date()
- Updated dependencies
- Added new
minifyOptionsoption to allow users to override the default configuration
- Updated dependencies
- The Nunjucks engine now uses
FileSystemLoaderfornode_modulesimports (very similar to how Sass engine works viaincludePaths), instead of deferring toNodeResolveLoader. That loader is not nearly as useful whennpminstalled packages use the new"export": { ... }format. Unless packages explicitly declare the non-JS exports you're unable to find them. I don't think we were using that anyway, so it's NBD.
- It is now possible to pass compiler options to Svelte via
svelteCompilerOptionsinbaker.config.js. Good for the rare case of when you need to render them as hydratable.
- Our custom Rollup
datasetPluginanddataPluginhave been moved to before@rollup/plugin-node-resolvein the Rollup plugin list. In some casesnodeResolvewould misinterpret the*:prefix and blow up the path before these plugins got a chance to do it first.
- The
{% static %}tag will now pass through full URLs as-is when used as the parameter. This lets developers not have to worry about whether a path is project relative or not in loops, and allows templates that work with files to easily account for local and remote files.
- Add
preventAssignment: trueto@rollup/plugin-replaceoptions.
- Make sure
process.exit(1)is called when builds fail.
- Pathing for Svelte CSS also needs to account for path prefixes or else it will be resolved incorrectly in HTML that's not at the root.
- Thanks to
@web/rollup-plugin-import-meta-assetsit's now possible to import paths to files within JavaScript and have that be enough to ensure that the file is added to the build. This is yet another method for loading data in baker projects, and likely the best one yet.
// Rollup will see this and understand it should add this file to your build
const url = new URL('./data/cities.json', import.meta.url);
// load it and go!
const data = await d3.json(url);- The Nunjucks environment is now allowed to cache templates in production mode. Probably won't change much speed wise, but ever so slightly more efficient.
A new experimental custom Rollup plugin has been added that provides an optimized method for importing data files in JavaScript. If a JSON, CSV, or TSV file is imported using the prefix dataset:* it will be added to the bundle either directly as an Object or Array literal (if under 10K in size) or rendered as a string within a JSON.parse call.
It has been documented that parsing a string within JSON.parse is much, much faster on average than directly passing in JavaScript, and typically this is the very first step when data is being loaded manually (with d3-fetch's json or csv functions, etc.). This makes it possible to import (or even better — dynamically import) data without having to deploy it as a file or inject it into HTML to be parsed.
An example of how to use it:
import data from 'dataset:./assets/data.json';
// or dynamically
const data = await import('dataset:./assets/data.json');- CSS within Svelte components is now supported. This means any CSS that's written within Svelte components will be included in the
{% script %}entrypoint bundle that is added to a page. - Additional variables are now available on the
pagetemplate context object (previouslycurrent_page) - in addition topage.absoluteUrl,page.urlrepresents the project-relative URL.page.inputPathrepresents the project-relative path to the original input template, andpage.outputPathrepresents the project-relative output path.
- The file watcher logic is now a little smarter and keeps track of dependencies directly in the engines (except for Rollup, which manages this itself). This is a small step toward having a much richer dependency graph for builds.
- The
current_pagetemplate context object has been renamed topage.current_pagehowever will continue to exist until1.0.
- It's now possible to supply custom tags (
{% custom variable1, variable2 %}) to Nunjucks via thebaker.config.jsfile. It is very similar to how you add custom filters.
How to add one:
// baker.config.js
module.exports = {
// ...
nunjucksTags: {
author(firstName, lastName) {
return `<p class="author">By ${firstName} ${lastName}</p>`;
},
},
};How to use one:
{% author "Arthur", "Barker" %}Heads up! Nunjucks requires a comma between arguments.
And the output:
<p class="author">By Arthur Barker</p>- Async nunjucks tags now must return a Promise. This abstracts away some of Nunjucks' warts and the expectation of a callback to enable async tags.
- Because the built-in
injecttag was async it now returns a Promise to match the new interface.
- Because users of
baker.config.jsno longer have access to the Baker instance, the function that resolves static files is now also available on the Nunjucks instance atgetStaticPath.
- A behind-the-scenes change, but the custom Rollup plugin for injecting imports into entrypoints has been replaced. This rids Baker of a bug that surfaces when attempting to use dynamic imports.
- Added TypeScript support to Svelte files via
svelte-preprocess. - Added an exported
svelte.config.jsfile so templates and other tools that need to mirror Baker'ssvelte-preprocessoptions can do so easily.
- Moved to
premovefromrimraffor directory-emptying tasks.
- The
jsonScriptfilter is now built-in to Baker's Nunjucks' environment. Much like the Django version, this filter safely outputs an object as JSON, wrapped in a <script> tag and ready for use with JavaScript. XSS attacks are mitigated by escaping the characters "<", ">" and "&".
This input:
{{ value|jsonScript("hello-data") }}Becomes this:
<script id="hello-data" type="application/json">
{ "hello": "world" }
</script>-
Attempting to use a JavaScript entrypoint that does not exist because compiling failed or because it was not configured as an entrypoint will now throw a more explicit (and helpful) error.
-
It's now possible to use ESM imports/exports when writing the
baker.config.jsfile. Hopefully this will make context switching less annoying - before it was the only user-facing JavaScript file that required CommonJS syntax.
-
The
static,staticabsoluteandinjectblocks will now always throw an error if a valid file cannot be found. Previously it would silently (and intentionally) fail so a missing file wasn't the end of the world while in development. Maybe this will be too drastic of a change but we'll have to see. Too often folks have a silent failure in development and don't realize it until their build fails in production. -
Nunjucks blocks and filters have been reorganized within Baker. Nothing user-facing should be altered by this.
- Bumped
mini-syncto 0.3.0 to catch a downstream change to do what we already thought was happening - all files served by the dev server should be receiving explicitno-cacheCache Control headers.
- Custom Nunjucks filters now have a reference to the current instance of the Nunjucks engine available at
this. Most filters will never need this, but we have a few cases where filters were hacking access in and we don't wanna break everything.
- The Nunjucks custom
logfilter now returns the input value so Nunjucks will not complain about a null or undefined output.
- It's now possible to use a configuration file to pass options to Baker when it is ran using the CLI. This is the preferred method for using Baker.
By default the CLI tool looks for a file called baker.config.js in the input directory when the --config (or -c) paramter is passed bare. You can also pass a path to a configuration file if you've given it another name or put it in another directory. If you do not pass --config it will use the defaults instead and any other parameters you pass.
# will look for "baker.config.js" in the current directory
baker bake --config
# will load the config in "my-config.js" in the current directory
baker bake --config my-config.js
# will not use any config *at all* even if it exists, and use all default options other than "input"
baker bake --input my-project-directoryThe configuration file should export an object off of module.exports. All options are optional, and Baker will still use the smart defaults the previous iteration of the CLI used. Only set things you want to explicitly change/add!
// baker.config.js
module.exports = {
// a custom domain for all resolved URLs
domain: 'our-news-domain',
// we want to use the static root feature, so we supply the path
staticRoot: '/static/',
// use createPages to generate pages on the fly
createPages(createPage, data) {
for (const title of data.titles) {
createPage('template.html', `${title}.html`, {
context: { title },
});
}
},
// pass an object of filters to add to Nunjucks
nunjucksFilters: {
square(n) {
n = +n;
return n * n;
},
},
};- It's now possible to add new Nunjucks filters using the
nunjucksFiltersconfiguration method. While it was always technically possible to add new filters before by reaching into Baker's instance of Nunjucks, this is a more user-friendly option that is available via the new config file method.
nunjucksFilters should be an object, where each key is the name of the filter, and the key's value is the function to call when the filter is used.
// baker.config.js
module.exports = {
nunjucksFilters: {
square(value) {
const n = +value;
return n * n;
},
},
};{% set value = 5 %}{{ value|square }} // 25- New
logfilter in Nunjucks templates that allows you to log any variable or value to the terminal's console.
{{ value|log }} // this variable should log in your terminal- Templates are now rendered sequentially instead of in parallel in an attempt to encourage some consistency in the order of errors being thrown. It's not uncommon to have an error present in multiple pages but because each one races each other to render it's not always the same page that throws. It's maddening. This may be slightly slower in bigger projects but we shall see.
- It's now possible to dynamically generate HTML outputs by passing an optional
createPagesfunction when you create aBakerinstance.
/**
* "createPages" is a function to call for each page you want created
* "data" is the quaff generated contents of the "_data" folder
*/
function createPages(createPage, data) {
// use whatever parts of the data context (or external sources!) to determine
// what pages should be generated
for (const title of data.titles) {
// call createPage for each one, passing in the template to use within
// _layouts, where to output it in the output (_dist) folder, and optional
// additional context
createPage('template.html', `${title}.html`, {
context: { title },
});
}
}
const baker = new Baker({
...,
createPages,
});This works whether you're running the development server locally or building for production.
If an optional additional context is passed, it will be merged with the global context only for that render and have precedence, meaning any overlapping keys will contain what was passed locally to createPage even if it also exists in the global context. It's recommended to do something similar to above and "namespace" your provided local context to lessen the chance of an unexpected overwrite.
- Moved from
rollup-plugin-babelto the namespaced@rollup/plugin-babel.
.json,.geojsonand.topojsonfiles in theassetsdirectory will now have hashes generated and work like you'd expect with{% static %}. In production these files will also be minified.
- Baker no longer uses
hashato calculate file hashes and instead rolls its own withcrypto, dropping two dependencies.
A new experimental Rollup plugin has been added to baker to provide an additional way to pull primitive values from files in the _data folder into JavaScript files. By importing a value from a special data:* path you can use the value directly.
So if there was meta.json file in your _data folder:
{
"breed": "corgi",
"names": ["Abe", "Winston", "Willow"]
}Then you could tap into it like this:
import breed from 'data:meta.breed';
console.log(breed); // "corgi"However - to prevent any excessively large imports this plugin will prevent the import of anything that's not a primitive value (number, boolean, string, etc.). This means no arrays or objects.
import names from 'data:meta.names'; // will throw a Rollup error!postcsswill now be ran against any CSS in development as well. This prevents the (increasingly) rare case of where a CSS property only has support with a prefix. (appearance: nonewas the driver for this.) This could cryptically break in development and then work in production, which is about as non-ideal as you can get.fs-extrahas been purged from the library in favor of nativefs.promisesandrimraf.- The CLI command now throws proper
process.exit()calls. - The dev server (via
mini-sync) now waits for the initial build to succeed before attempting to serve. This should help prevent partial serves and throw more helpful errors if there is something critically wrong without leaving the dev server in limbo. - We now use
colorettefor all our terminal coloring needs.
- Failures to process a file in the
_datadirectory will now throw legitmate errors viaquaff. In the case of JSON this means you'll get actually useful line numbers.
- It's now possible to pass a
staticRootpath to Baker, which will make every non-HTML engine output into thestaticRootrelative tooutput. This is intented to make multi-page deploys more viable in certain scenarios.
- Each HTML page generated by Nunjucks now has access to the local context variable
current_page. As of this release the only value in this object iscurrent_page.absolute_url, which is intended to replace the globalCURRENT_URL.
- The
CURRENT_URLNunjucks global is no longer available, and has been replaced by the local context objectcurrent_page. Please note this now means any usage ofcurrent_pagemust be passed into macros, who do not have access to the local context.
- The
CURRENT_URLNunjucks global was subject to a race condition when Baker is in multiple-page output mode due to the async render method. This means it was possible for an HTML page to use the wrongCURRENT_URL. Now, the current URL of a page will appear on a local context variable calledcurrent_page.absolute_url, guaranteeing that each page can only ever see it's owncurrent_pagecontext.
- The included
preloadvia{% script %}now passescrossorigin.
- The preload section of the
{% script %}block now accounts for thepathPrefixand resolves relative to it.
- It's now possible to pass a second flag to the
{% script %}block that instructs it to include any scripts that are candidates for preloading. This is recommended in browsers that supportrel=preloadin order to assist the browser in efficiently loading assets. You should only use this if something like Lighthouse is suggesting it. To activate it, just passtrueas the second parameter to{% script %}and Baker will do the rest.
{% script 'app', true %}dotenv-expandhas been added to our.envfile logic, allowing for tapping into existing environment variables to build valuesbakercan see. theBAKER_prefix is still enforced, however - but this provides a way to morph existing variables into compatible ones.
- The reworked
injectfunction from0.15.0did not account for local development when a manifest does not exist forAssetsEngineoutput. This has been fixed. It instead will look for the local version of the file indevelopmentand continue to error out inproductionif the manifest check fails.
@babel/preset-typescriptalso needs to know what the JSX pragma is so it knows to ignore it. This patch ensures both@babel/preset-typescriptand@babel/plugin-transform-react-jsxget passed the same one.
- Added support for TypeScript (
.ts,.tsx) files in thescriptsdirectory via@babel/preset-typescript. They are also allowed asentrypointsif passed. Actual type-checking is left up to the user, all this does is remove any TypeScript artifacts from the files - BYOtsconfig.jsonandtsccalls.
- Added a reworked
injectblock, which allows for inserting the contents of a file post processing directly into the HTML. This is useful for potentially "injecting" CSS or JavaScript into the page.
- Video files (
.mp4,.webm) are now recognized byAssetsEngineand will be included in any hashing.
- Some
dependenciesgot moved todevDependencies, meaning you wouldn't have got them on install. Oops.
Baker.pathPrefixis now set to/indevelopmentmode so a passedpathPrefixdoes not break anything in serve mode.
- The Nunjucks environment now includes a new global named
CURRENT_URL. This represents the final URL of each generated page that can be used in its template. It's based on a combination of the provideddomain,pathPrefixand clean (withoutindex.htmlappended) path of the output HTML itself.
- Added new built-in
datefilter to Nunjucks, which allows for formatting of an ISO date string or Date object withdate-fnsformatting function. - Added a new parameter that must be passed to
new Baker()—domain. This is used bystaticabsoluteto prepare absolute project URLs. (May become optional later for scenarios where this doesn't matter.) - Added new
staticabsoluteblock, which makes it possible to build absolute URLs to project files.
- Font files (
.woff2,.woff,.ttf,.otf) are now recognized byAssetsEngineand will be included in any hashing.
- Baker now picks up images with without all lowercase extensions and includes them the compression and hashing process.
- The function that resolves static files is now available on a Baker instance as
getStaticPath. This enables users of Baker to tap into the file resolution logic however they see fit.
- Modern JavaScript builds now use
@babel/preset-modules. This should result in even smaller modern bundles that natively support features that already exist in ~85% of browsers.
- Automatic web polyfill injection has been removed. It's just too much magic going on, and we shouldn't assume that every single thing will need
fetch+intersection-observer+classlistinjected into it. (JavaScript features are still polyfilled viacore-js. In other words if it's something you'd be able to do in Node.js it's handled.) The gains of keeping a few polyfills out of the modern build aren't worth the confusion. However this does mean users are now responsible for importing their own polyfills.
- The Rollup engine now supports both Svelte (
.sveltefiles) and Preact (the usage of JSX) as options for JavaScript-based HTML templating.
browser-synchas been replaced withmini-sync.browser-syncwas one of the largest packages installed inbaker, and this should lead to quicker install times.
- The old legacy Rollup engine has been deleted and the one previously called
rollup2.jshas taken its place.
- Support for correctly formatted environment variables that are passed to
rollup-plugin-replacehas been added. Any environment variable that begins withBAKER_will be read and converted to theprocess.env.BAKER_*format that can be used in JavaScript files. Any environmental variables that do not have a match are ignored.
It's also possible to manage these with a .env in the root of your project. The same rule regarding the BAKER_ prefix applies.
- Two custom functions have been added to the
sassrenderer —static-urlandstatic-path. These are implemented against the Node.js API (and not within a Sass file) because they need to reference the static asset manifests. They are used in the same scenarios as the{% static %}block in Nunjucks templates — you need to reference the path to a static asset in your project, but need it to be given the correct hash prefix on production builds.
static-url is meant to be a shortcut for anything you'd normally put inside of url(), which it will include for you.
SCSS
body {
background-image: static-url('assets/background.png');
}CSS
body {
background-image: url(/assets/background.123abc.png);
}static-path only adjusts the path and returns it as a string. This will probably be less used, but it's there as an escape hatch if you need it.
body {
background-image: url(static-path('assets/background.png'));
}CSS
body {
background-image: url(/assets/background.123abc.png);
}- Now only valid images will receive the file hash in production mode. This is imperfect, but better than every random asset getting a hash unnecessarily and causing issues when they're used. (Looking at you,
.gltffiles.) Ideally this would be smarter, but not quite sure how to go about that yet.
- Nunjucks templates now have a better error logger. It's not perfect, but should help find specific lines causing issues.
- Template files in the layout directory are now watched during a serve - if any changes are made templates are regenerated.
- Files in the
datadirectory are now watched during a serve and will trigger a template build.
- This package is now deployed on
npmat@datagraphics/bakerinstead of@datadesk/baker, which has been deprecated.
- Legacy script builds now use
core-jsto polyfill and add features that may be missing in those browsers. This will likely cause theiifebuild to be bigger than it should be, but this prevents users from having to whack-a-mole issues with IE 11. It should just work. - Polyfills for both the modern and legacy are automatically inserted into every entrypoint, with the assumption there's a base set of features we should expect to be there. For modern builds, it's support for dynamic imports and IntersectionObserver. For legacy builds, it's fetch, Element.classList and IntersectionObserver.
- The engine for Rollup has been rewritten to be much smarter about how it navigates modern and legacy builds. This also does away with SystemJS in favor of native modules for browsers that support it, and an
iifebuild for browsers that do not.
- Added
AssetsEnginefor management of generic assets files in a build. By default it looks for anassetsdirectory in the input directory.
- The
ImagesEngineis no more and has been merged intoAssetsEngine. This means that images must be in theassetsdirectory to be found and handled.
- A
pathPrefixshould always have a leading slash to ensure pathing resolution works.
- The serve task now runs all the engines in an initial pass before activating the server. This ensures that the local development URL is not presented as available before it truly is.
- Initial release.