Optimize data uris as build time

This commit is contained in:
Jordan Eldredge 2019-03-02 14:41:49 -08:00
parent cfa0fd235e
commit 5c8f01cc4d
9 changed files with 1051 additions and 40 deletions

View file

@ -11,7 +11,20 @@ module.exports = {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
use: [
"style-loader",
{ loader: "css-loader", options: { importLoaders: 1 } },
// We really only need this in prod. We could find a way to disable it in dev.
{
loader: "postcss-loader",
options: {
plugins: [
require("cssnano"),
require("../scripts/postcss-optimize-data-uri-pngs")
]
}
}
]
},
{
test: /\.(js|ts|tsx)$/,

File diff suppressed because one or more lines are too long

View file

@ -14,7 +14,16 @@ module.exports = {
use: [
"style-loader",
{ loader: "css-loader", options: { importLoaders: 1 } },
"postcss-loader"
// We really only need this in prod. We could find a way to disable it in dev.
{
loader: "postcss-loader",
options: {
plugins: [
require("cssnano"),
require("../../scripts/postcss-optimize-data-uri-pngs")
]
}
}
]
},
{

View file

@ -34,7 +34,7 @@ import {
} from "./actionTypes";
import Emitter from "./emitter";
import "../css/base-skin.min.css";
import "../css/base-skin.css";
import { SerializedStateV1 } from "./serializedStates/v1Types";
import Disposable from "./Disposable";

View file

@ -80,6 +80,7 @@
"copy-webpack-plugin": "^4.6.0",
"css-loader": "^1.0.1",
"cssnano": "^4.1.10",
"data-uri-to-buffer": "^2.0.0",
"eslint": "4.16.0",
"eslint-config-prettier": "^2.3.0",
"eslint-plugin-import": "^2.7.0",
@ -93,6 +94,8 @@
"html-webpack-plugin": "^3.2.0",
"http-server": "^0.11.1",
"idb-kv-store": "^4.4.0",
"imagemin": "^6.1.0",
"imagemin-optipng": "^6.0.0",
"invariant": "^2.2.3",
"jest": "^23.5.0",
"jest-image-snapshot": "^2.4.1",
@ -103,6 +106,7 @@
"lodash": "^4.17.11",
"milkdrop-preset-converter-aws": "^0.1.6",
"music-metadata-browser": "^0.6.1",
"postcss": "^7.0.14",
"postcss-loader": "^3.0.0",
"prettier": "^1.16.0",
"prop-types": "^15.5.10",

View file

@ -1,3 +0,0 @@
module.exports = {
plugins: [require("cssnano")]
};

View file

@ -0,0 +1,37 @@
const postcss = require("postcss");
const dataUriToBuffer = require("data-uri-to-buffer");
const imagemin = require("imagemin");
const imageminOptipng = require("imagemin-optipng");
const DATA_URL_REGEX = new RegExp(/url\((data:image\/png;base64,.+)\)/gi);
const DATA_URL_PROPS_REGEX = /^(background(?:-image)?)|(content)|(cursor)/;
async function optimizeDataUri(dataUri) {
const buffer = dataUriToBuffer(dataUri);
const optimized = await imagemin.buffer(buffer, {
use: [imageminOptipng()]
});
return `data:image/png;base64,${optimized.toString("base64")}`;
}
module.exports = postcss.plugin("postcss-optimize-data-uri-pngs", () => {
return async function(css) {
// walkDecls does not let us work async, so we collect the async work we
// need to do here, and await it at the end
const promisesFactories = [];
css.walkDecls(DATA_URL_PROPS_REGEX, decl => {
let matches;
// WTF JavaScript. This is the worst API for iterating RegEx matches.
while ((matches = DATA_URL_REGEX.exec(decl.value))) {
const [, dataUri] = matches;
promisesFactories.push(async () => {
decl.value = decl.value.replace(
dataUri,
await optimizeDataUri(dataUri)
);
});
}
});
await Promise.all(promisesFactories.map(p => p()));
};
});

View file

@ -0,0 +1,10 @@
const fs = require("fs");
const postcss = require("postcss");
const plugin = require("./postcss-optimize-data-uri-pngs");
const css = fs.readFileSync("./css/base-skin.css", "utf8");
it("does something", async () => {
const result = await postcss([plugin({})]).process(css);
expect(result.css.length).toBeLessThan(css.length);
});

1008
yarn.lock

File diff suppressed because it is too large Load diff