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

ERROR Template execution failed: TypeError: Cannot read property 'entry' of undefined

Open gabrielrtakeda opened this issue 3 years ago • 9 comments

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

Maybe a bug...

What is the current behaviour?

After upgrading preact-cli to v3.0.4 I'm getting the error below, after running preact build

✖ ERROR Template execution failed: TypeError: Cannot read property 'entry' of undefined

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

After adding the same changes of #1490 in my local node_modules preact-cli installation to be able to pass --no-prerender option properly, I've executed:

yarn preact build --no-sw --no-esm --no-prerender --no-inline-css

What is the expected behaviour?

Apparently it's building the code properly but, since the build script exists with code 1, it breaks CI the workflow.. (Also, it's generating a new file called 200.html)

image-preact-cli

Please mention other relevant information.

Opening the 200.html file it prints out the html below:

image

cat /var/folders/40/hmnm06wd6dv_q5pklkjdh5dc0000gn/T/preact-cli/template.tmp.ejs

Click to expand

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8">
		<title><%= htmlWebpackPlugin.options.title %></title>
		<meta name="viewport" content="width=device-width,initial-scale=1">
		<meta name="mobile-web-app-capable" content="yes">
		<meta name="apple-mobile-web-app-capable" content="yes">
		<link rel="apple-touch-icon" href="/assets/icons/apple-touch-icon.png">
		<link rel="manifest" href="<%= htmlWebpackPlugin.files.publicPath %>manifest.json">
<% if (htmlWebpackPlugin.options.manifest.theme_color) { %>
	<meta name="theme-color" content="<%= htmlWebpackPlugin.options.manifest.theme_color %>">
<% } %>
<% const loadManifest = htmlWebpackPlugin.options.createLoadManifest(compilation.assets, webpack.namedChunkGroups);%>
<% const filesRegexp = htmlWebpackPlugin.options.inlineCss ? /\.(chunk\.\w{5}\.css|js)$/ : /\.(css|js)$/;%>
<% for (const file in loadManifest[htmlWebpackPlugin.options.url]) { %>
	<% if (htmlWebpackPlugin.options.preload && file && file.match(filesRegexp)) { %>
		<% /* crossorigin for main bundle as that is loaded from `<script type=module` tag, other lazy loaded bundles are from webpack so its not needed */ %>
		<link rel="preload" href="<%= htmlWebpackPlugin.files.publicPath + file %>" as="<%= file.match(/\.css$/)?'style':'script' %>" <%= file.match(/bundle\.\w{5}\.esm\.js$/)?'crossorigin="anonymous"':'' %>>
	<% } %>
<% } %>

	</head>
	<body>
		<%= htmlWebpackPlugin.options.ssr() %>
<script type="__PREACT_CLI_DATA__">
	<%= encodeURI(JSON.stringify(htmlWebpackPlugin.options.CLI_DATA)) %>
</script>
<% if (webpack.assets.filter(entry => entry.name.match(/bundle(\.\w{5})?.esm.js$/)).length > 0) { %>
	<% /* Fix for safari < 11 nomodule bug. TODO: Do the following only for safari. */ %>
	<script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
	<script crossorigin="anonymous" src="<%= htmlWebpackPlugin.files.publicPath %><%= webpack.assets.filter(entry => entry.name.match(/bundle(\.\w{5})?.esm.js$/))[0].name %>" type="module"></script>
	<%
		/*Fetch and Promise polyfills are not needed for browsers that support type=module
		Please re-evaluate below line if adding more polyfills.*/
	%>
	<script nomodule src="<%= htmlWebpackPlugin.files.chunks["polyfills"].entry %>"></script>
	<script nomodule defer src="<%= htmlWebpackPlugin.files.chunks['bundle'].entry %>"></script>
<% } else { %>
	<script <%= htmlWebpackPlugin.options.scriptLoading %>  src="<%= htmlWebpackPlugin.files.chunks['bundle'].entry %>"></script>
	<script nomodule src="<%= htmlWebpackPlugin.files.chunks["polyfills"].entry %>"></script>
<% } %>

	</body>
</html>

I'm not using a custom template so, I think it's related to the bump of ejs-loader from 0.37 to 0.5.0 in PR #1403

Please paste the results of preact info here.

Environment Info:
  System:
    OS: macOS 10.15.7
    CPU: (12) x64 Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
  Binaries:
    Node: 14.11.0 - /var/folders/40/hmnm06wd6dv_q5pklkjdh5dc0000gn/T/yarn--1607536942927-0.1841710342107825/node
    Yarn: 1.22.10 - /var/folders/40/hmnm06wd6dv_q5pklkjdh5dc0000gn/T/yarn--1607536942927-0.1841710342107825/yarn
    npm: 6.14.8 - ~/.nvm/versions/node/v14.11.0/bin/npm
  Browsers:
    Chrome: 87.0.4280.88
    Firefox: 77.0.1
    Safari: 14.0.1
  npmPackages:
    preact: ^10.5.7 => 10.5.7
    preact-cli: ^3.0.4 => 3.0.4
    preact-render-to-string: ^5.1.12 => 5.1.12

gabrielrtakeda avatar Dec 09 '20 18:12 gabrielrtakeda

As a temporary workaround, I've added an empty template.html into my project's src...

gabrielrtakeda avatar Dec 09 '20 18:12 gabrielrtakeda

do you have any changes in template.html

prateekbh avatar Dec 09 '20 18:12 prateekbh

No, I don't... I've added an empty file to "override" the default template here

gabrielrtakeda avatar Dec 09 '20 18:12 gabrielrtakeda

by any chance is your repo public?

prateekbh avatar Dec 09 '20 19:12 prateekbh

Sorry, it isn't.. But I can share the preact.config.js

gabrielrtakeda avatar Dec 10 '20 13:12 gabrielrtakeda

I had the same problem. Short explanation is that preact-cli expects 2 hardcoded entries for prerendering, and you'll get this error if you don't provide them. If I'm not mistaken, it's designed to work with only one entry module (and polyfills).

In this exact example the problem is that you are defining multiple custom entry chunks, and Preact is expecting only bundle and polyfills chunks.

The application I'm working on has a few public pages and an app that has a few more pages, and I wanted to separate them to have service worker only for non public pages and to have a smaller main bundle for public pages. My solution was:

  • extract .ejs template. There should be /tmp/preact-cli/template.tmp.ejs on Unix like systems after build. Since I had just 2 entries 2 different .ejs template files worked for me.
  • define my own entry based on this module. I simplified it because I'm using it only for production builds. This line is where you should change it to use your app root module https://github.com/preactjs/preact-cli/blob/master/packages/cli/lib/lib/entry.js#L31
  • Replace template and chunks in HtmlWebpackPlugin plugins. Here's an example

Note that I'm not sure if this is an optimal solution at this point and I hope there will be a simpler solution after https://github.com/preactjs/preact-cli/issues/1108.

bojan88 avatar May 07 '21 03:05 bojan88

I had the same problem. Short explanation is that preact-cli expects 2 hardcoded entries for prerendering, and you'll get this error if you don't provide them. If I'm not mistaken, it's designed to work with only one entry module (and polyfills).

In this exact example the problem is that you are defining multiple custom entry chunks, and Preact is expecting only bundle and polyfills chunks.

The application I'm working on has a few public pages and an app that has a few more pages, and I wanted to separate them to have service worker only for non public pages and to have a smaller main bundle for public pages. My solution was:

  • extract .ejs template. There should be /tmp/preact-cli/template.tmp.ejs on Unix like systems after build. Since I had just 2 entries 2 different .ejs template files worked for me.
  • define my own entry based on this module. I simplified it because I'm using it only for production builds. This line is where you should change it to use your app root module https://github.com/preactjs/preact-cli/blob/master/packages/cli/lib/lib/entry.js#L31
  • Replace template and chunks in HtmlWebpackPlugin plugins. Here's an example

Note that I'm not sure if this is an optimal solution at this point and I hope there will be a simpler solution after #1108.

hiii @bojan88 !

I know it's been a while since you posted this but I was hoping you could explain this step..

define my own entry based on [this module](https://github.com/preactjs/preact-cli/blob/master/packages/cli/lib/lib/entry.js). I simplified it because I'm using it only for production builds. This line is where you should change it to use your app root module https://github.com/preactjs/preact-cli/blob/master/packages/cli/lib/lib/entry.js#L31

Did you have an example of how you changed the entry? I'm running into this same issue but can't figure it out :(

any help would be appreciated, thank youu!!

jennyylau avatar Aug 05 '22 12:08 jennyylau

I know it's been a while since you posted this but I was hoping you could explain this step..

  • define my own entry based on this module. I simplified it because I'm using it only for production builds. This line is where you should change it to use your app root module https://github.com/preactjs/preact-cli/blob/master/packages/cli/lib/lib/entry.js#L31

Did you have an example of how you changed the entry? I'm running into this same issue but can't figure it out :(

The lack of a perma-link here is what throws this off.

Here's the actual line you'd want to alter: https://github.com/preactjs/preact-cli/blob/6aba5d8e4c165c81f258ca9f367fea6c9a08cf17/packages/cli/lib/lib/entry.js#L32

preact-cli-entrypoint is just an alias defined in the Webpack config that points to <src directory>/index: https://github.com/preactjs/preact-cli/blob/6aba5d8e4c165c81f258ca9f367fea6c9a08cf17/packages/cli/lib/lib/webpack/webpack-base-config.js#L141-L143

It can be replace with anything, however.

As a maintainer I wouldn't necessarily recommend this, but it's how you could provide a secondary entry point.

rschristian avatar Aug 05 '22 19:08 rschristian

I know it's been a while since you posted this but I was hoping you could explain this step..

  • define my own entry based on this module. I simplified it because I'm using it only for production builds. This line is where you should change it to use your app root module https://github.com/preactjs/preact-cli/blob/master/packages/cli/lib/lib/entry.js#L31

Did you have an example of how you changed the entry? I'm running into this same issue but can't figure it out :(

The lack of a perma-link here is what throws this off.

Here's the actual line you'd want to alter:

https://github.com/preactjs/preact-cli/blob/6aba5d8e4c165c81f258ca9f367fea6c9a08cf17/packages/cli/lib/lib/entry.js#L32

preact-cli-entrypoint is just an alias defined in the Webpack config that points to <src directory>/index:

https://github.com/preactjs/preact-cli/blob/6aba5d8e4c165c81f258ca9f367fea6c9a08cf17/packages/cli/lib/lib/webpack/webpack-base-config.js#L141-L143

It can be replace with anything, however.

As a maintainer I wouldn't necessarily recommend this, but it's how you could provide a secondary entry point.

Hii thanks so much for the quick reply!!

I think I figured out how to do what I wanted to do without messing with the entry file or changing the alias here.

jennyylau avatar Aug 07 '22 21:08 jennyylau