electron-webpack
electron-webpack copied to clipboard
__static doesn't work for CSS files in development
- electron-builder: 22.7.0
- electron-webpack: 2.8.2
- electron: 9.1.1
- Target: electron-renderer
Background
I want to support custom CSS themes in my application. I want to provide a default theme in case the user has not provided their own. This file should not be preprocessed / compiled by webpack, other than simply being duplicated to the appropriate location in the bundle.
It is my understanding that the static/ folder is the appropriate place to put such a file.
Setup
Project Structure
I organized my project according to the recommended project structure:
root/
src/
renderer/
renderer.ts
static/
theme.css
Contents of theme.css: (make everything red so it's obvious when the theme is active)
body {
color: red;
background-color: red;
font-size: 72px;
}
Contents of renderer.ts:
\\...
let cssPath = getStatic('theme.css')
console.log("STATIC", cssPath);
let linkElt = document.createElement("link");
linkElt.setAttribute("rel", "stylesheet");
linkElt.setAttribute("type", "text/css");
linkElt.setAttribute("href", cssPath);
document.head.appendChild(linkElt);
\\...
My Attempt
According to the documentation for "Using Static Assets",
__static is made available to provide you a path to your static/ folder. This variable is available in both development and production.
However, from my tests, this statement is incorrect, and __static produces meaningless URLs during development. So, I am attempting to use the getStatic() solution to make static files accessible to the renderer during both development and production.
import path from 'path'
import * as url from 'url'
const isDevelopment = process.env.NODE_ENV !== 'production';
declare const __static:string;
// see https://github.com/electron-userland/electron-webpack/issues/241#issuecomment-582920906
export function getStatic(relativePath:string = "") {
if (isDevelopment) {
return url.resolve(window.location.origin, relativePath)
}
return path.resolve(__static, relativePath)
}
The Problem
Expected Behavior
- The
getStatic()function should return a path totheme.css - The renderer should be able to correctly load
theme.cssfrom a<link>element
Actual Behavior
When I run the app with electron-webpack dev, I get the following error in the renderer:
Refused to apply style from 'http://localhost:9080/theme.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled
My debug print also shows that getStatic("theme.css") resolves to http://localhost:9080/theme.css. If I try to visit this location in a browser, I get the following error. The renderer probably gets the same error when trying to load this path, which explains the MIME type exception.
Cannot GET /theme.css
My guess is that this path simply does not exist, since I get a similar error if I visit a nonsensical URL like http://localhost:9080/asdfasdfasdfasdf.css.
@benrbray I just tried to reproduce, starting from scratch with electron-webpack-quick-start, but it just worked..
Here's an example repo: https://github.com/loopmode/electron-webpack-static-examples
The initial commit basically covers your case already.
This is literally all there is:

Development server:
Production build installed and launched after setup:
Production build executed directly from dist/win-unpacked folder:
@develar Embedding static assets still confuses users, and the docs don't properly cover development vs production. I'll add explanation to the docs soonish, but should we also link this issue or the example repo in the docs?
The example currently covers static stylesheet and static image (from code), but I'll add custom font and background image (from css) as well.
Thanks @loopmode for the detailed example! It would be an excellent addition to the documentation.
Unfortunately for me, my project is large enough that I've already had to modify the electron-webpack config to support tsx, some babel-plugins, etc.. As a result I had trouble pinpointing exact differences between your working example and my own project.
Instead, I managed to get it to work using copy-webpack-plugin:
new CopyWebpackPlugin({
patterns: [
{ from: 'static' }
]
}),