nextron icon indicating copy to clipboard operation
nextron copied to clipboard

Support for Nextjs 13.3 Static export

Open Brandontam29 opened this issue 3 years ago • 12 comments

Can we upgrade to Nextjs13 without breaking the application?

Update May 2023:

Next export is deprecated in favor of Static export read more here: https://nextjs.org/docs/app/building-your-application/deploying/static-exports#next-export-deprecated

Brandontam29 avatar Nov 15 '22 20:11 Brandontam29

You can use official cli tool from the next team.

Upgrade images:

npx @next/codemod next-image-to-legacy-image ./renderer/pages

Upgrade links:

npx @next/codemod new-link ./renderer/pages

vxxvvxxv avatar Nov 18 '22 04:11 vxxvvxxv

Is the NextJS 13 pages folder structure working out of the box?

dohomi avatar Feb 22 '23 04:02 dohomi

Is the NextJS 13 pages folder structure working out of the box?

Unfortunately, no

vxxvvxxv avatar Feb 22 '23 05:02 vxxvvxxv

This will be supported in the next release of Next on 13.3 https://beta.nextjs.org/docs/configuring/static-export, so we should be able to add it.

dbredvick avatar Mar 31 '23 15:03 dbredvick

Hey, I'm totally new to nextron/next, but am looking to start a project on it. Do you have any hints on how to make the new app folder structure work? I guess just adding the static-export configuration won't be enough? 😅

ealeksandrov7 avatar Apr 27 '23 07:04 ealeksandrov7

Next 13.4 was launched with stable release of app folder, is time to go ahead with the support. https://nextjs.org/blog/next-13-4

andirsun avatar May 04 '23 20:05 andirsun

Hey, I tried to update electron to the last version 25.1.0 and then I wasn't able to use client component (all my useEffect wasn't triggered).

I also try to update Next.JS -> same problem But If I downgrade electron to 21 and up next is works

It seems related to this issue with static pages

// packages.json
 "devDependencies": {
    "@types/node": "^20.3.0",
    "@types/react": "^18.2.11",
    "electron": "^21.3.3",
    "electron-builder": "^23.6.0",
    "next": "^12.3.4",
    "nextron": "^8.5.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "typescript": "^5.1.3"
  }

castroCrea avatar Jun 11 '23 18:06 castroCrea

I've started some next13 support work at /jonstelly/nextron/tree/feature/next13.

For next 13 with App Router, I think the recommended way to generate the equivalent of the deprecated next export is to just set output: export in the next.config.js, at which point next build will spit out a static bundle/build.

I wonder about doing the following:

  1. Modify next.config.js and add output: export (this is now like next build && next export)
  2. Modify nextron-build to not call "next export", instead copy the exported-output from step 1 to appdir
  3. If the goal of nextron is to support next 13 but retain support for previous versions of next, either:
  • auto-detect if we're on next 13 or not and still call next export if on <=12?
  • add a --next13 flag to nextron build <- I started with this for simplicity
  • add to the nextron config

It also feels like with nextjs app router, appdir should probably be something other than app? I'm not an electron expert but I think we could change the appdir in nextron and the files filter in electron-builder.yaml to include a different directory than 'app'?

Any feedback on what's there so far? I'm going to create a new example on that branch to scaffold an empty next13 app.

I've got the above branch building and bundling to electron, launching that bundle gives an error:

A JavaScript error occurred in the main process
Uncaught Exception:
Error: ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: 908
    at Object.set [as exports] (/.../app/dist/linux-unpacked/resources/app.asar/app/background.js:2:121398)

so I'm tracking that down now.

jonstelly avatar Jul 01 '23 16:07 jonstelly

I've got this working:

nextron fork - https://github.com/jonstelly/nextron/tree/feature/next13 Example Repo/App - https://github.com/jonstelly/nextron13

A couple remaining problems:

  • setting output: 'export' means you don't run a separate next export and next build doesn't allow an outDir argument. So I added distDir: '../app' to the next.config to have build write it there directly. That feels clunky
  • The main/background typescript files don't get compiled. I'm not sure what I broke with webpack.config.js. My hack was to just include the .js files in /main

Aside: In my project I've added capacitor so I can also create android and ios builds. It might be another good nextron example/template to add. If I get everything working reasonably I'll generate an example for that too.

Nice work on nextron, it makes nice work of bringing next and electron together.

jonstelly avatar Jul 01 '23 22:07 jonstelly

Hey,

I just tried your nextron13 branch, with [email protected] and electron@21 and everything seems to run. I also try to update Electron to the last version, `25.2.0, ' which runs too.

  1. Note that after yarn install on the first yarn dev I got this error image

      At second `yarn dev` works well
    
  2. For the useState and useEffect are not working when adding 'use client' It should be working according to the next doc image

https://github.com/saltyshiomix/nextron/assets/20707343/205616a4-3c3e-4ab7-982a-e67640fc8215

I added a PR with my tried that doesn't work https://github.com/jonstelly/nextron13/pull/1/files

castroCrea avatar Jul 06 '23 10:07 castroCrea

I also tried to build on mac OS without signing and got this errors image

I check it is there image

I also tried with you original cmd but --next13 doesn't seems to be an option image

image

castroCrea avatar Jul 06 '23 11:07 castroCrea

Hi everyone,

in my repo I was also able to run it with a few adoptions. I will create a small summary for everyone searching for quick & dirty solution until the official Nextron Update is there:

My setup: Next 13.4.9 & Electron 21.3.3 & Nextron 8.5.0

1. Adoptions to next.config.js

const config = {
	webpack: (config, { isServer }) => {
		if (!isServer) {
			config.target = 'electron-renderer'
		}
		return config
	},
}

if (process.env.NODE_ENV === 'production') {
	config.output = 'export'
	config.distDir = '../app'
	config.images = {
		loader: 'custom',
		loaderFile: './image-loader.js',
	}
}

module.exports = config

2. New file image-loader.js

'use client';

// External loader because Electron does not support the default loader in production mode.
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export default function myImageLoader({ src, width, quality }) {
	return `app://./${src}?w=${width}&q=${quality || 75}`;
}

I needed an external image loader because my images did not loaded with the default engine from NextJS with the static exports. So I built my own.

3. Changes in NPM Package of nextron

Now it gets dirty:

I changed a small line in the delivered NPM package of nextron so that the following error disappeared during built process error "next export -o <dir>" cannot be used when "output: export" is configured in next.config.js. Instead add "distDir" in next.config.js https://nextjs.org/docs/advanced-features/static-html-export

We have to remove the command next export from nextron's built process.

New /bin/nextron-build.js

#!/usr/bin/env node
"use strict";var e=require("fs-extra"),n=require("path"),o=require("arg"),i=require("chalk"),r=require("execa"),a=require("fs");require("webpack-merge"),require("webpack");const l=process.cwd();require(n.join(l,"package.json")).dependencies;const s=process.cwd();a.existsSync(n.join(s,"tsconfig.json"));function c(e){console.log(i`{cyan [nextron]} ${e}`)}const t=o({"--help":Boolean,"--version":Boolean,"--all":Boolean,"--win":Boolean,"--mac":Boolean,"--linux":Boolean,"--x64":Boolean,"--ia32":Boolean,"--armv7l":Boolean,"--arm64":Boolean,"--universal":Boolean,"--config":String,"--publish":String,"--no-pack":Boolean,"-h":"--help","-v":"--version","-w":"--win","-m":"--mac","-l":"--linux","-c":"--config","-p":"--publish"});t["--help"]&&(console.log(i`
    {bold.cyan nextron build} - Build and export the application for production deployment

    {bold USAGE}

      {bold $} {cyan nextron build} --help
      {bold $} {cyan nextron build} [options]

    {bold OPTIONS}

      --help,    -h  show this help message
      --version, -v  display the current version of nextron
      --all          build for Windows, macOS and Linux
      --win,     -w  build for Windows, accepts target list (see https://goo.gl/jYsTEJ)
      --mac,     -m  build for macOS, accepts target list (see https://goo.gl/5uHuzj)
      --linux,   -l  build for Linux, accepts target list (see https://goo.gl/4vwQad) 
      --x64          build for x64
      --ia32         build for ia32
      --armv7l       build for armv7l
      --arm64        build for arm64
      --universal    build for mac universal binary
      --no-pack      skip electron-builder pack command
      --publish, -p  publish artifacts (see https://goo.gl/tSFycD)
                     [choices: "onTag", "onTagOrDraft", "always", "never", undefined]

  `),process.exit(0));const u=process.cwd(),p={cwd:u,stdio:"inherit"};function d(){let e=[];return t["--x64"]&&e.push("--x64"),t["--ia32"]&&e.push("--ia32"),t["--armv7l"]&&e.push("--armv7l"),t["--arm64"]&&e.push("--arm64"),t["--universal"]&&e.push("--universal"),e}!async function(){process.env.ELECTRON_BUILDER_ALLOW_UNRESOLVED_DEPENDENCIES="true";const o=n.join(u,"app"),l=n.join(u,"dist"),h=(()=>{const e=n.join(s,"nextron.config.js");return a.existsSync(e)?require(e):{}})().rendererSrcDir||"renderer";try{c("Clearing previous builds"),e.removeSync(o),e.removeSync(l),c("Building renderer process"),await r("next",["build",n.join(u,h)],p),await r("node",[n.join(__dirname,"webpack.config.js")],p),t["--no-pack"]?c("Skip Packaging..."):(c("Packaging - please wait a moment"),await r("electron-builder",function(){let e=[];t["--config"]&&(e.push("--config"),e.push(t["--config"]||"electron-builder.yml"));t["--publish"]&&(e.push("--publish"),e.push(t["--publish"]));t["--all"]?(e.push("-wml"),e.push(...d())):(t["--win"]&&e.push("--win"),t["--mac"]&&e.push("--mac"),t["--linux"]&&e.push("--linux"),e.push(...d()));return e}(),p)),c("See `dist` directory")}catch(e){console.log(i`

{bold.red Cannot build electron packages:}
{bold.yellow ${e}}
`),process.exit(1)}}();

Alternatively you can use one of the forks from above to build your process. Only there!!! the --next-13 command line switch will work.

I hope this helpful :)

SimonFrank14 avatar Jul 09 '23 15:07 SimonFrank14

@Brandontam29 @vxxvvxxv @dohomi @dbredvick @ealeksandrov7 @andirsun @castroCrea @jonstelly @SimonFrank14

Sorry for late reply and inconvenience.

I just released nextron v9.0.0, which supports next.js v13 and v14. If you have time, please try it :)


NOTE:

Please update renderer/next.config.js as belows:

module.exports = {
  output: 'export',
  // we want to change distDir to "app" so as nextron can build the app in production mode!
  distDir: process.env.NODE_ENV === 'production' ? '../app' : '.next',
  trailingSlash: true,
  images: {
    unoptimized: true,
  },
}

saltyshiomix avatar Jun 16 '24 07:06 saltyshiomix

I'll close this issue, but feel free to reopen it if any updates :)

saltyshiomix avatar Jul 21 '24 02:07 saltyshiomix