Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Nuxt v4 template #18

Merged
merged 6 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ Our plan is to release the first version when all Vite templates are ready:

Later we will add support for meta-frameworks:
- [x] `Nuxt 3` template (from `v0.1.0`)
- [x] `Nuxt 3 Compatibility Version 4 (Nuxt 4)` template (from `v0.4.0`)
- [x] `SvelteKit` template (from `v0.2.0`)
- [ ] `Astro` template
- [x] `Remix` template (from `v0.3.0`)
Expand Down
6 changes: 4 additions & 2 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
- [x] `react` and `react-ts` templates
- [x] `preact` and `preact-ts` templates
- [x] `solid` and `solid-ts` templates
- [x] `nuxt` template (from `v0.1.0`)
- [x] `nuxt 3` template (from `v0.1.0`)
- [x] `nuxt 3 v4-compat` template (from `v0.4.0`)
- [x] `sveltekit` template (from `v0.2.0`)
- [ ] `astro` template
- [x] `remix` template (from `v0.3.0`)
Expand All @@ -28,7 +29,8 @@
- [x] `react` and `react-ts` templates
- [x] `preact` and `preact-ts` templates
- [x] `solid` and `solid-ts` templates
- [x] `nuxt` template
- [x] `nuxt 3` template
- [x] `nuxt 3 v4-compat` template
- [x] `sveltekit` template
- [ ] `astro` template
- [x] `remix` template
Expand Down
5 changes: 4 additions & 1 deletion src/customize/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ export async function customize(prompts: PromptsData) {
await import('./svelte').then(({ customize }) => customize(prompts))
break
case 'custom-nuxt':
await import('./nuxt').then(({ customize }) => customize(prompts))
await import('./nuxt').then(({ customize }) => customize(prompts, false))
break
case 'custom-nuxt-v4':
await import('./nuxt').then(({ customize }) => customize(prompts, true))
break
case 'custom-remix':
await import('./remix').then(({ customize }) => customize(prompts))
Expand Down
161 changes: 117 additions & 44 deletions src/customize/nuxt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,20 @@ import {
WorkboxVersion,
} from '../versions'

export async function customize(prompts: PromptsData) {
export async function customize(prompts: PromptsData, v4: boolean) {
const {
cdProjectName,
templateDir,
rootPath,
templateDir: templateDirFolder,
rootPath: outputRootPath,
customServiceWorker,
prompt,
pwaAssets,
} = prompts
const [rootPath, templateDir] = getPaths(outputRootPath, templateDirFolder, v4)
// cleanup target folder
fs.rmSync(path.join(rootPath, 'app.vue'), { recursive: true })
fs.rmSync(path.join(rootPath, 'nuxt.config.ts'), { recursive: true })
fs.rmSync(path.join(rootPath, 'public'), { recursive: true })
fs.rmSync(path.join(outputRootPath, 'nuxt.config.ts'), { recursive: true })
fs.rmSync(path.join(outputRootPath, 'public'), { recursive: true })
// extract template-nuxt folder
fs.copyFileSync(path.join(templateDir, 'app.vue'), path.join(rootPath, 'app.vue'))
fs.mkdirSync(path.join(rootPath, 'layouts'))
Expand All @@ -44,28 +45,51 @@ export async function customize(prompts: PromptsData) {
path.join(templateDir, 'pages', 'index.vue'),
path.join(rootPath, 'pages', 'index.vue'),
)
fs.mkdirSync(path.join(rootPath, 'public'))
fs.copyFileSync(path.join(templateDir, 'public', 'favicon.svg'), path.join(rootPath, 'public', 'favicon.svg'))
fs.copyFileSync(path.join(templateDir, 'pwa-assets.config.ts'), path.join(rootPath, 'pwa-assets.config.ts'))
fs.mkdirSync(path.join(outputRootPath, 'public'))
fs.copyFileSync(path.join(templateDir, 'public', 'favicon.svg'), path.join(outputRootPath, 'public', 'favicon.svg'))

// v4 root inside app: public folder on root
if (v4 && pwaAssets) {
const pwaAssets = fs.readFileSync(path.join(templateDir, 'pwa-assets.config.ts'), 'utf-8')
fs.writeFileSync(
path.join(outputRootPath, 'app/pwa-assets.config.ts'),
pwaAssets.replace('images: [\'public/favicon.svg\'],', 'images: [\'../public/favicon.svg\'],'),
'utf-8',
)
}
else {
fs.copyFileSync(path.join(templateDir, 'pwa-assets.config.ts'), path.join(outputRootPath, 'pwa-assets.config.ts'))
}

if (customServiceWorker) {
fs.mkdirSync(path.join(rootPath, 'service-worker'))
fs.copyFileSync(
path.join(templateDir, 'service-worker', `${prompt ? 'prompt' : 'claims'}-sw.ts`),
path.join(rootPath, 'service-worker', 'sw.ts'),
)
fs.copyFileSync(
path.join(templateDir, 'service-worker', 'tsconfig.json'),
path.join(rootPath, 'service-worker', 'tsconfig.json'),
)
if (v4) {
const tsConfig = fs.readFileSync(path.join(templateDir, 'service-worker', 'tsconfig.json'), 'utf-8')
fs.writeFileSync(
path.join(rootPath, 'service-worker', 'tsconfig.json'),
tsConfig.replace('"extends": "../tsconfig.json",', '"extends": "../../tsconfig.json",'),
'utf-8',
)
}
else {
fs.copyFileSync(
path.join(templateDir, 'service-worker', 'tsconfig.json'),
path.join(rootPath, 'service-worker', 'tsconfig.json'),
)
}
}

// create nuxt.config.ts
createNuxtConf(prompts)
createNuxtConf(prompts, v4)

// prepare package.json
const pkg = JSON.parse(fs.readFileSync(path.join(rootPath, 'package.json'), 'utf-8'))
const pkg = JSON.parse(fs.readFileSync(path.join(outputRootPath, 'package.json'), 'utf-8'))

const pkgManager = await detectPackageManager(rootPath).then(res => res?.name || 'npm')
const pkgManager = await detectPackageManager(outputRootPath).then(res => res?.name || 'npm')

// dependencies
pkg.dependencies ??= {}
Expand Down Expand Up @@ -95,10 +119,10 @@ export async function customize(prompts: PromptsData) {
includeDependencies(prompts, pkgManager === 'npm', pkg, true)

// save package.json
fs.writeFileSync(path.join(rootPath, 'package.json'), JSON.stringify(pkg, null, 2), 'utf-8')
fs.writeFileSync(path.join(outputRootPath, 'package.json'), JSON.stringify(pkg, null, 2), 'utf-8')

console.log('\n\nPWA configuration done. Now run:\n')
if (rootPath !== process.cwd()) {
if (outputRootPath !== process.cwd()) {
console.log(
` cd ${
cdProjectName.includes(' ') ? `"${cdProjectName}"` : cdProjectName
Expand All @@ -122,7 +146,7 @@ export async function customize(prompts: PromptsData) {
console.log()
}

function createNuxtConf(prompts: PromptsData) {
function createNuxtConf(prompts: PromptsData, v4: boolean) {
const {
rootPath,
customServiceWorker,
Expand Down Expand Up @@ -157,32 +181,7 @@ function createNuxtConf(prompts: PromptsData) {
pwaOptions.client.installPrompt = true
}

const nuxtConf = customServiceWorker
? parseModule(`// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
typescript: {
tsConfig: {
exclude: ['../service-worker'],
},
},
devtools: { enabled: true },
nitro: {
prerender: {
routes: ['/'],
},
},
})
`)
: parseModule(`// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: true },
nitro: {
prerender: {
routes: ['/'],
},
},
})
`)
const nuxtConf = prepareNuxtConf(customServiceWorker === true, v4)
addNuxtModule(nuxtConf, '@vite-pwa/nuxt', 'pwa', pwaOptions)
fs.writeFileSync(
path.join(rootPath, 'nuxt.config.ts'),
Expand Down Expand Up @@ -313,3 +312,77 @@ function createLayout(prompts: PromptsData) {

return content
}

function prepareNuxtConfV3(customServiceWorker: boolean): ReturnType<typeof parseModule> {
return customServiceWorker
? parseModule(`// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
typescript: {
tsConfig: {
exclude: ['../service-worker'],
},
},
devtools: { enabled: true },
nitro: {
prerender: {
routes: ['/'],
},
},
})
`)
: parseModule(`// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: true },
nitro: {
prerender: {
routes: ['/'],
},
},
})
`)
}

function prepareNuxtConfV4(customServiceWorker: boolean): ReturnType<typeof parseModule> {
return customServiceWorker
? parseModule(`// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
future: {
compatibilityVersion: 4
},
typescript: {
tsConfig: {
exclude: ['../app/service-worker'],
},
},
devtools: { enabled: true },
nitro: {
prerender: {
routes: ['/'],
},
},
})
`)
: parseModule(`// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
future: {
compatibilityVersion: 4
},
devtools: { enabled: true },
nitro: {
prerender: {
routes: ['/'],
},
},
})
`)
}

function getPaths(rootPath: string, templateDir: string, v4: boolean): [rootPath: string, templateDir: string] {
return v4
? [path.join(rootPath, 'app'), templateDir.replace('template-custom-nuxt-v4', 'template-custom-nuxt')]
: [rootPath, templateDir]
}

function prepareNuxtConf(customSW: boolean, v4: boolean): ReturnType<typeof parseModule> {
return v4 ? prepareNuxtConfV4(customSW) : prepareNuxtConfV3(customSW)
}
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ async function init() {
inactive: 'no',
},
{
type: (_, { variant }) => variant === 'custom-nuxt' ? 'toggle' : null,
type: (_, { variant }) => variant === 'custom-nuxt' || variant === 'custom-nuxt-v4' ? 'toggle' : null,
name: 'installPWA',
message: reset('Add PWA Install Prompt?'),
initial: false,
Expand Down
7 changes: 7 additions & 0 deletions src/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ export const FRAMEWORKS = (<Framework[]>[
customCommand: 'npm exec nuxi init TARGET_DIR',
enabled: true,
},
{
name: 'custom-nuxt-v4',
display: 'Nuxt 4 ↗',
color: cyan,
customCommand: 'npx nuxi@latest init -t v4-compat TARGET_DIR',
enabled: true,
},
],
},
{
Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface Framework {

export type FrameworkVariantKey =
| 'vanilla' | 'vanilla-ts'
| 'vue' | 'vue-ts' | 'custom-nuxt'
| 'vue' | 'vue-ts' | 'custom-nuxt' | 'custom-nuxt-v4'
| 'react' | 'react-ts'
| 'preact' | 'preact-ts'
| 'svelte' | 'svelte-ts' | 'custom-svelte-kit'
Expand Down
6 changes: 3 additions & 3 deletions src/versions.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export const WorkboxVersion = '^7.1.0'
export const VitePluginPWAVersion = '^0.20.0'
export const VitePluginPWAVersion = '^0.20.1'
export const PWAAssetsVersion = '^0.2.4'
export const NuxtPWAModuleVersion = '^0.7.0'
export const SvelteKitPWAVersion = '^0.5.0'
export const NuxtPWAModuleVersion = '^0.9.1'
export const SvelteKitPWAVersion = '^0.6.0'
export const RemixPWAVersion = '^0.1.0'
export const TypeScriptVersion = '^5.4.5'
export const VueTscVersion = '^2.0.16'
Expand Down