electron-webpack icon indicating copy to clipboard operation
electron-webpack copied to clipboard

__static doesn't work for CSS files in development

Open benrbray opened this issue 5 years ago • 3 comments

  • 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 to theme.css
  • The renderer should be able to correctly load theme.css from 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 avatar Aug 16 '20 21:08 benrbray

@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: image

Development server: electron-webpack-static-css-dev

Production build installed and launched after setup: electron-webpack-static-css-prod-installed

Production build executed directly from dist/win-unpacked folder: electron-webpack-static-css-prod

loopmode avatar Aug 17 '20 05:08 loopmode

@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.

loopmode avatar Aug 17 '20 06:08 loopmode

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' }
	]
}),

benrbray avatar Aug 17 '20 17:08 benrbray