preact-cli icon indicating copy to clipboard operation
preact-cli copied to clipboard

Custom render-html-plugin method

Open cortopy opened this issue 5 years ago • 5 comments

Do you want to request a feature or report a bug? Request a feature

What is the current behaviour? Preact-cli uses its own html-render-plugin and it's very difficult to extend. For example, in L54 it seems like the prerender method can be customised. But how does one get to pass the configuration for it?

If the current behaviour is a bug, please provide the steps to reproduce.

What is the expected behaviour?

If this is a feature request, what is motivation or use case for changing the behaviour?

I would like to be able to extend render-html-plugin for my own purposes like:

  • Using a css-in-js library that supports SSR
  • Injecting data as initial state etc.

Please mention other relevant information.

I would like to start a discussion on which would be the best way to accomplish this. Would a PR that aims to do the following look good?

  • [ ] extract render-html-plugin as a separate package in the preact-cli monorepo (and use this plugin as default at this stage)
  • [ ] as a next step, make render-html-plugin configurable by initialising it in preact.config.js. If not initialised then behaviour can be using default settings maybe
  • [ ] alternative plugins can also be initialised in preact.config.js, in which case render-html-plugin is not used

Please paste the results of preact info here.

cortopy avatar Jul 22 '19 09:07 cortopy

Ah!! I've just realised something like this is already discussed in https://github.com/preactjs/preact-cli/pull/839

cortopy avatar Jul 22 '19 09:07 cortopy

Hi! Yes, the cases u listed seems like valid use cases. The approach also seems fine.

alternative plugins can also be initialized in preact.config.js, in which case render-html-plugin is not used

Is the only part i am not sure about as the setting in the the template.html are the key to the performance promised by preact-cli

prateekbh avatar Jul 22 '19 22:07 prateekbh

Hi! Yes, the cases u listed seems like valid use cases. The approach also seems fine.

alternative plugins can also be initialized in preact.config.js, in which case render-html-plugin is not used

Is the only part i am not sure about as the setting in the the template.html are the key to the performance promised by preact-cli

That would be the ultimate case when a developer knows what s/he is doing and prefers using her/his own prerender plugin. In this proposal, if nothing is provided in the config in regards to prerendering, then all the defaults are used, so users should not experience anything different to what preact-cli does now. This shouldn't be a breaking change

cortopy avatar Jul 29 '19 20:07 cortopy

I've just run into this problem too. It would be nice to have an escape hatch for customising the prerender.

I managed to find a solution after reading the preact-cli source code and coming up with an elaborate workaround that doesn't involve forking the repo.

I'll detail the workaround here for other people running into the same issues. The problem I was trying to solve was that there was a FOUC when using material-ui because their styles were not being inlined, but this could easily be the case for styled-components, emotion etc.

// index.js - export a function to use later
import { ServerStyleSheets } from '@material-ui/core/styles';
import renderToString from 'preact-render-to-string';

export const createCss = () => {
	const sheets = new ServerStyleSheets();

	renderToString(
		sheets.collect(<App />)
	);

	return sheets.toString();
};

create a plugin by creating a preact.config.js file so that we can add a function to the HtmlWebpackPlugin

const { resolve } = require('path');

const createServerStyleSheets = (env) => () => {
	if (!env.ssr) {
		let entry = resolve(env.dest, './ssr-build/ssr-bundle.js');
    
		return require(entry).createCss();
	}
};

export default (config, env, helpers) => {
	const createCss = createServerStyleSheets(env);

	const plugins = helpers.getPluginsByName(config, 'HtmlWebpackPlugin');
	plugins.forEach((p) => {
		p.plugin.options.css = createCss;
	});
};

Create a template.html which is a copy of the default preact-cli one except with the extra line of injected inline styles where we call the function we attached in the custom plugin.

    <style id="jss-server-side"><%= htmlWebpackPlugin.options.css() %></style>

This took me a while to figure out. It would be great if there was a way to do this with a config option.

kenny-f avatar Nov 16 '19 13:11 kenny-f

I created a solution for styled-components that adds support for stylesheet SSR in preact-cli, and doesn't really require any special configuration or tweaks (aside from defining an SSR constant that we should probably have added in core anyway).

You can check it out here: https://gist.github.com/developit/23fc4995c3b2c07bd8ff3f916565bb03

developit avatar Apr 02 '20 22:04 developit