preact-cli
preact-cli copied to clipboard
How to build preact in one index.html file?
Hey. I use preact to create interactive pages that are hosted in the memory of the microcontroller. The preact size and features are really impressive, but for my use case it is still overloaded.
What can I do so that when I run the npm run build command, I get 1 file - index.html, where will all the styles and scripts be inside?
I used to have a working version, but when updating webpack and preact, it turned out to be not working:
package.json
"build": "preact build --no-prerender --no-service-worker"
preact.config.js
export default (config, env, helpers) => {
const chunks = helpers.getPluginsByName(config, 'CommonsChunkPlugin')[0]
config.plugins[chunks.index].minChunks = 1
}
Thanks!
I used to have a working version, but when updating webpack and preact, it turned out to be not working
What's the error message your getting?
Try replacing your preact.config.js with this:
export default (config, env, helpers) => {
config.optimization.splitChunks.minChunks = 1;
}
Should this issue be migrated to the preact-cli
repo?
Hey @BRAGA96 did you end up making any progress with this? I am in the exact situation using a microcontroller, and am also interested in condensing the build files into a single html file
I made this but it was not so easy as a one liner
https://gist.github.com/sebasjm/087df4b0b0a611ce409fe30a67a1d0d9
Any improvement would be greatly appreciated.
Any solution yet? @sebasjm's solution doesnt look like a good way of doing this
I just need to inline scripts and styles, nothing more than that
Tried to use react-dev-utils/InlineChunkHtmlPlugin
and my preact.config.js looks like this:
import HtmlWebpackPlugin from "html-webpack-plugin";
import InlineChunkHtmlPlugin from "react-dev-utils/InlineChunkHtmlPlugin";
export default (config, env, helpers) => {
config.plugins.push(
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/.+[.]js/])
);
}
Build goes:
0% (0.0s) compiling× ERROR TypeError: this.htmlWebpackPlugin.getHooks is not a function
at \node_modules\react-dev-utils\InlineChunkHtmlPlugin.js:43:44
at SyncHook.eval [as call] (eval at create (\node_modules\tapable\lib\HookCodeFactory.js:19:10), <anonymous>:27:1)
at SyncHook.lazyCompileHook (\node_modules\tapable\lib\Hook.js:154:20)
at Compiler.newCompilation (\node_modules\webpack\lib\Compiler.js:631:26)
at \node_modules\webpack\lib\Compiler.js:667:29
at AsyncSeriesHook.eval [as callAsync] (eval at create (\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:6:1)
at AsyncSeriesHook.lazyCompileHook (\node_modules\tapable\lib\Hook.js:154:20)
at Compiler.compile (\node_modules\webpack\lib\Compiler.js:662:28)
at \node_modules\webpack\lib\Compiler.js:321:11
at Compiler.readRecords (\node_modules\webpack\lib\Compiler.js:529:11)
at \node_modules\webpack\lib\Compiler.js:318:10
at AsyncSeriesHook.eval [as callAsync] (eval at create (\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:6:1)
at AsyncSeriesHook.lazyCompileHook (\node_modules\tapable\lib\Hook.js:154:20)
at \node_modules\webpack\lib\Compiler.js:315:19
at AsyncSeriesHook.eval [as callAsync] (eval at create (\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:15:1)
at AsyncSeriesHook.lazyCompileHook (\node_modules\tapable\lib\Hook.js:154:20)
So https://github.com/jantimon/html-webpack-plugin/issues/1068 says 'getHooks is new in html-webpack-plugin 4.0.0.alpha-2'
and you have "html-webpack-plugin": "^3.2.0",
and I mentioned is #1629 that you can't install another version
What should I do?
@caxapexac You installed the latest version of html-webpack-plugin
which isn't compatible, yes. You can try an older version, and you may need to downgrade whatever utility that is as well.
Is there anything about the above solution that makes you think it is a poor way of going about this (assuming it works as you'd like it to)?
@rschristian it uses grep, I use windows It uses something strange while webpack plugins just casually exist
Nothing strange about a post-build script, and I'd argue that is the correct way to go about this. Way less fragile than depending on Webpack plugins, that depend on specific versions of other dependencies, Webpack features, and our configuration.
You could swap grep and sed out for a Node script, fs.readFile
and whatnot, it'd be just as effective.
[email protected] doesn't work either cuz of html-webpack-plugin (https://stackoverflow.com/a/60473584/9398364)
html-webpack-inline-source-plugin ^0.0.10 doesn't work cuz its for webpack4
We are using Webpack 4
https://github.com/DustinJackson/html-webpack-inline-source-plugin/issues/79 with 0.0.10
Nothing strange about a post-build script, and I'd argue that is the correct way to go about this. Way less fragile than depending on Webpack plugins, that depend on specific versions of other dependencies, Webpack features, and our configuration.
@rschristian its just so essential task (bundling 3 files into 1 file) so writing regexp with string replace looks like writing array sorting by hand, whats wrong if I want to write 1 string inside webpack config instead of remembering sick syntax of regexp?
Ouf this is building with "html-webpack-inline-source-plugin": "^0.0.10",:
import HtmlWebpackPlugin from "html-webpack-plugin";
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
export default (config, env, helpers) => {
config.plugins.push(new HtmlWebpackPlugin({
inlineSource: '.(js|css)$'
}))
config.plugins.push(new HtmlWebpackInlineSourcePlugin())
}
Nothing's wrong with with that, but the fact of the matter is that you have a lot more moving pieces with Webpack plugins. As you've already encountered, you have a reliance upon not only your plugin version, but webpack
, html-webpack-plugin
, and preact-cli
versions. Scripts remain static. Grep, for comparison, has remained the same for decades, and that's why I'd recommend that over plugins which may or may not work in the future, especially when it's as small and isolated as what's needed here. That's just my opinion though, you're free to do whatever you choose of course.
This likely isn't something we're looking to support out-of-the-box, as it's quite a bad practice if you can avoid it, so you'll need to do a bit of stitching things together if you cannot find a webpack plugin that'll work with our current dependencies.
There is #1608 in the pipeline which will upgrade us to html-webpack-plugin
v4, but there's no ETA on when that might be ready or released.
Okay I've re-read https://github.com/preactjs/preact-cli/issues/923#issuecomment-870605603 and it seems legit, sorry for all this stuff Ive said.
So if I use this solution, to what should I replace 'something.woff' and 'base64-inline-loader' on the 15-20th line to not to break everything and have truly single-file bundle (I can have js, css, png, svg in the project)? (it is good to inline js as base64? How to inline as plain text?)
@rschristian my pipeline is updated and now its legit to use multiple files in build. Whats the best command for build then? I use preact for rendering game overlay gui so no need for prerendering and other stuff:
I suupose its preact build --no-sw --no-esm
but maybe there is more to add?
I.e. css dedupe (#1631) - I can't fully disable inlined css cuz its needed for loading screen What about --prerender also?
The aim is to having folder: assets/ favicon.ico index.html (with inlined loading screen css) bundle.css (without loading screen css) index.min.js
P.S. is there anything wrong making game interface with react? Honestly I don't know, is there other legit solutions? (I've seen vue used for game ui only)
Disabling prerendering would mean very little CSS could be inlined. Critters needs to be able to detect what styles you use in order to inline those CSS rules. If you don't prerender, you're handing Critters an empty doc; it will only end up inlining generic rules for body
and html
.
@rschristian its okay about css and prerender, got it, thanks. What about 3-files build? There are still files I'd like to get rid off, is it possible?:
I mean:
prerender data now only contain {"url":"/"}
and doesn't look useful
push manifest and ssr doesn't look like used at all, what is it?
ssr-build/
is used to prerender your app, push-manifest.json
is beneficial with http2 push, see: https://github.com/GoogleChromeLabs/http2-push-manifest#whats-a-push-manifest
You can just run a post-build delete script for anything you don't want. I doubt you want the manifest.
Oh I see, push manifest feels much useful now, thanks
Sorry, push-manifest
you could want, manifest.json
is what I was referring to with that last comment. They're for PWAs, but seeing as how you've disabled the rest of the PWA stuff, you don't want it.
What kinds of pwa stuff had I disabled? I really need manifest.json so I thought service worker is optional for it
There's no hard requirement, though it'd be quite odd.
Going to close out, this will never be supported out-of-the-box. Users can configure via preact.config.js
if they require this.