Process images with Webpack

This adds a `file-loader` rule to the Webpack build so that any requests for
image resource will be output into the app's output directory, but with an extra
content has appended so that we can safely use a long cache lifetime.

The CSS and SCSS rules are also changed to use `css-loader` so that any `url`
inside is automatically processed by the new image rule above.
This commit is contained in:
J. Ryan Stinnett 2018-12-31 17:22:47 -06:00
parent e3d807b053
commit 49be03e845
4 changed files with 599 additions and 181 deletions

721
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -33,8 +33,8 @@
"build:res": "node scripts/copy-res.js", "build:res": "node scripts/copy-res.js",
"build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js", "build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js",
"build:compile": "npm run reskindex && babel --source-maps -d lib src", "build:compile": "npm run reskindex && babel --source-maps -d lib src",
"build:bundle": "cross-env NODE_ENV=production webpack-cli -p --progress --bail --mode production", "build:bundle": "cross-env NODE_ENV=production webpack -p --progress --bail --mode production",
"build:bundle:dev": "webpack-cli --progress --bail --mode development", "build:bundle:dev": "webpack --progress --bail --mode development",
"build:electron": "npm run clean && npm run build && npm run install:electron && build -wml --ia32 --x64", "build:electron": "npm run clean && npm run build && npm run install:electron && build -wml --ia32 --x64",
"build:react-sdk": "node scripts/npm-sub.js matrix-react-sdk run build", "build:react-sdk": "node scripts/npm-sub.js matrix-react-sdk run build",
"build:js-sdk": "node scripts/npm-sub.js matrix-js-sdk run start:init", "build:js-sdk": "node scripts/npm-sub.js matrix-js-sdk run start:init",
@ -100,6 +100,7 @@
"concurrently": "^4.0.1", "concurrently": "^4.0.1",
"cpx": "^1.3.2", "cpx": "^1.3.2",
"cross-env": "^4.0.0", "cross-env": "^4.0.0",
"css-loader": "^2.1.0",
"electron-builder": "^20.29.0", "electron-builder": "^20.29.0",
"electron-builder-squirrel-windows": "^11.6.1", "electron-builder-squirrel-windows": "^11.6.1",
"electron-devtools-installer": "^2.2.4", "electron-devtools-installer": "^2.2.4",
@ -110,6 +111,7 @@
"eslint-plugin-flowtype": "^2.50.3", "eslint-plugin-flowtype": "^2.50.3",
"eslint-plugin-react": "^7.11.1", "eslint-plugin-react": "^7.11.1",
"expect": "^1.16.0", "expect": "^1.16.0",
"file-loader": "^3.0.1",
"fs-extra": "^0.30.0", "fs-extra": "^0.30.0",
"html-webpack-plugin": "^3.2.0", "html-webpack-plugin": "^3.2.0",
"json-loader": "^0.5.3", "json-loader": "^0.5.3",
@ -136,7 +138,6 @@
"postcss-scss": "^1.0.6", "postcss-scss": "^1.0.6",
"postcss-simple-vars": "^4.1.0", "postcss-simple-vars": "^4.1.0",
"postcss-strip-inline-comments": "^0.1.5", "postcss-strip-inline-comments": "^0.1.5",
"raw-loader": "^0.5.1",
"react-addons-perf": "^15.4.0", "react-addons-perf": "^15.4.0",
"react-addons-test-utils": "^15.6.0", "react-addons-test-utils": "^15.6.0",
"rimraf": "^2.4.3", "rimraf": "^2.4.3",

View file

@ -53,9 +53,9 @@ const COPY_LIST = [
["res/home.html", "webapp"], ["res/home.html", "webapp"],
["res/home-status.html", "webapp"], ["res/home-status.html", "webapp"],
["res/home/**", "webapp/home"], ["res/home/**", "webapp/home"],
["res/vector-icons/**", "webapp/vector-icons"],
["node_modules/matrix-react-sdk/res/{fonts,img,themes,media}/**", "webapp"],
["res/themes/**", "webapp/themes"], ["res/themes/**", "webapp/themes"],
["res/vector-icons/**", "webapp/vector-icons"],
["node_modules/matrix-react-sdk/res/media/**", "webapp/media"],
["node_modules/emojione/assets/svg/*", "webapp/emojione/svg/"], ["node_modules/emojione/assets/svg/*", "webapp/emojione/svg/"],
["node_modules/emojione/assets/png/*", "webapp/emojione/png/"], ["node_modules/emojione/assets/png/*", "webapp/emojione/png/"],
// XXX: This is tied quite heavily to the matching olm.js so it really should be // XXX: This is tied quite heavily to the matching olm.js so it really should be

View file

@ -28,23 +28,21 @@ module.exports = {
{ {
test: /\.scss$/, test: /\.scss$/,
// 1. postcss-loader turns the SCSS into normal CSS. // 1. postcss-loader turns the SCSS into normal CSS.
// 2. raw-loader turns the CSS into a javascript module // 2. css-loader turns the CSS into a JS module whose default
// whose default export is a string containing the CSS. // export is a string containing the CSS, while also adding
// (raw-loader is similar to css-loader, but the latter // the images and fonts from CSS as Webpack inputs.
// would also drag in the imgs and fonts that our CSS refers to
// as webpack inputs.)
// 3. ExtractTextPlugin turns that string into a separate asset. // 3. ExtractTextPlugin turns that string into a separate asset.
use: ExtractTextPlugin.extract({ use: ExtractTextPlugin.extract({
use: [ use: [
"raw-loader", "css-loader",
{ {
loader: 'postcss-loader', loader: 'postcss-loader',
options: { options: {
config: { config: {
path: './postcss.config.js' path: './postcss.config.js',
} },
} },
} },
], ],
}), }),
}, },
@ -52,10 +50,33 @@ module.exports = {
// this works similarly to the scss case, without postcss. // this works similarly to the scss case, without postcss.
test: /\.css$/, test: /\.css$/,
use: ExtractTextPlugin.extract({ use: ExtractTextPlugin.extract({
use: "raw-loader" use: "css-loader",
}), }),
}, },
{
test: /\.(gif|png|svg|ttf)$/,
loader: 'file-loader',
options: {
// Use a content-based hash in the name so that we can set a
// long cache lifetime for assets while still delivering
// changes quickly.
name: '[name].[hash:7].[ext]',
outputPath: function(url, resourcePath, context) {
// Merge assets found via CSS and imports into a single
// tree, while also preserving directories under **/res.
const prefix = /^.*\/res\//;
const outputDir = path.dirname(resourcePath).replace(prefix, "");
return path.join(outputDir, path.basename(url));
},
publicPath: function(url, resourcePath, context) {
// Merge assets found via CSS and imports into a single
// tree, while also preserving directories under **/res.
const prefix = /^.*\/res\//;
const outputDir = path.dirname(resourcePath).replace(prefix, "");
return path.join("../..", outputDir, path.basename(url));
},
},
},
], ],
noParse: [ noParse: [
// for cross platform compatibility use [\\\/] as the path separator // for cross platform compatibility use [\\\/] as the path separator
@ -75,14 +96,13 @@ module.exports = {
output: { output: {
path: path.join(__dirname, "webapp"), path: path.join(__dirname, "webapp"),
// the generated js (and CSS, from the ExtractTextPlugin) are put in a // The generated JS (and CSS, from the ExtractTextPlugin) are put in a
// unique subdirectory for the build. There will only be one such // unique subdirectory for the build. There will only be one such
// 'bundle' directory in the generated tarball; however, hosting // 'bundle' directory in the generated tarball; however, hosting
// servers can collect 'bundles' from multiple versions into one // servers can collect 'bundles' from multiple versions into one
// directory and symlink it into place - this allows users who loaded // directory and symlink it into place - this allows users who loaded
// an older version of the application to continue to access webpack // an older version of the application to continue to access webpack
// chunks even after the app is redeployed. // chunks even after the app is redeployed.
//
filename: "bundles/[hash]/[name].js", filename: "bundles/[hash]/[name].js",
chunkFilename: "bundles/[hash]/[name].js", chunkFilename: "bundles/[hash]/[name].js",
devtoolModuleFilenameTemplate: function(info) { devtoolModuleFilenameTemplate: function(info) {