diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 513682b8ec..0000000000 --- a/.eslintrc +++ /dev/null @@ -1,168 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/eslintrc", - "ignorePatterns": [ - "dist", - "public", - "node_modules", - "packages/schema/schema" - ], - "globals": { - "NodeJS": true, - "$fetch": true - }, - "plugins": ["jsdoc", "import", "unicorn", "no-only-tests"], - "extends": [ - "plugin:jsdoc/recommended", - "@nuxt/eslint-config", - "plugin:import/typescript" - ], - "rules": { - "sort-imports": [ - "error", - { - "ignoreDeclarationSort": true - } - ], - "no-only-tests/no-only-tests": "error", - "unicorn/prefer-node-protocol": "error", - "no-console": "warn", - "vue/one-component-per-file": "off", - "vue/require-default-prop": "off", - - // Vue stylistic rules from `@antfu/eslint-config` - "vue/array-bracket-spacing": ["error", "never"], - "vue/arrow-spacing": ["error", { "after": true, "before": true }], - "vue/block-spacing": ["error", "always"], - "vue/block-tag-newline": [ - "error", - { - "multiline": "always", - "singleline": "always" - } - ], - "vue/brace-style": ["error", "stroustrup", { "allowSingleLine": true }], - "vue/comma-dangle": ["error", "always-multiline"], - "vue/comma-spacing": ["error", { "after": true, "before": false }], - "vue/comma-style": ["error", "last"], - "vue/html-comment-content-spacing": [ - "error", - "always", - { - "exceptions": ["-"] - } - ], - "vue/key-spacing": ["error", { "afterColon": true, "beforeColon": false }], - "vue/keyword-spacing": ["error", { "after": true, "before": true }], - "vue/object-curly-newline": "off", - "vue/object-curly-spacing": ["error", "always"], - "vue/object-property-newline": [ - "error", - { "allowMultiplePropertiesPerLine": true } - ], - "vue/operator-linebreak": ["error", "before"], - "vue/padding-line-between-blocks": ["error", "always"], - "vue/quote-props": ["error", "consistent-as-needed"], - "vue/space-in-parens": ["error", "never"], - "vue/template-curly-spacing": "error", - - "jsdoc/require-jsdoc": "off", - "jsdoc/require-param": "off", - "jsdoc/require-returns": "off", - "jsdoc/require-param-type": "off", - "import/order": [ - "error", - { - "pathGroups": [ - { - "pattern": "#vue-router", - "group": "external" - } - ] - } - ], - "import/no-restricted-paths": [ - "error", - { - "zones": [ - { - "from": "packages/nuxt/src/!(core)/**/*", - "target": "packages/nuxt/src/core", - "message": "core should not directly import from modules." - }, - { - "from": "packages/nuxt/src/!(app)/**/*", - "target": "packages/nuxt/src/app", - "message": "app should not directly import from modules." - }, - { - "from": "packages/nuxt/src/app/**/index.ts", - "target": "packages/nuxt/src", - "message": "should not import from barrel/index files" - }, - { - "from": "packages/nitro", - "target": "packages/!(nitro)/**/*", - "message": "nitro should not directly import other packages." - } - ] - } - ], - "@typescript-eslint/consistent-type-imports": [ - "error", - { - "disallowTypeAnnotations": false - } - ], - "@typescript-eslint/ban-ts-comment": [ - "error", - { - "ts-expect-error": "allow-with-description", - "ts-ignore": true - } - ], - "@typescript-eslint/prefer-ts-expect-error": "error", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "argsIgnorePattern": "^_", - "varsIgnorePattern": "^_", - "ignoreRestSiblings": true - } - ], - "jsdoc/check-tag-names": [ - "error", - { - "definedTags": ["__NO_SIDE_EFFECTS__"] - } - ] - }, - "overrides": [ - { - "files": ["packages/schema/**"], - "rules": { - "jsdoc/valid-types": "off", - "jsdoc/check-tag-names": [ - "error", - { - "definedTags": ["experimental"] - } - ] - } - }, - { - "files": ["packages/nuxt/src/app/**", "test/**", "**/runtime/**"], - "rules": { - "no-console": "off" - } - } - ], - "settings": { - "jsdoc": { - "ignoreInternal": true, - "tagNamePreference": { - "warning": "warning", - "note": "note" - } - } - } -} diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 7b2d765c12..ff8f4c2377 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,10 +1,10 @@ blank_issues_enabled: true contact_links: - name: πŸ“š Nuxt 3 Documentation - url: https://nuxt.com/docs/ + url: https://nuxt.com/docs about: Check the documentation for usage of Nuxt 3 - name: πŸ“š Nuxt 2 Documentation - url: https://v2.nuxt.com/ + url: https://v2.nuxt.com about: Check the documentation for usage of Nuxt 2 - name: πŸ’¬ Discussions url: https://github.com/nuxt/nuxt/discussions diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index f99be3b89d..8cba9c0e73 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,37 +1,19 @@ - - ### πŸ”— Linked issue - - -### ❓ Type of change - - - -- [ ] πŸ“– Documentation (updates to the documentation, readme or JSdoc annotations) -- [ ] 🐞 Bug fix (a non-breaking change that fixes an issue) -- [ ] πŸ‘Œ Enhancement (improving an existing functionality like performance) -- [ ] ✨ New feature (a non-breaking change that adds functionality) -- [ ] 🧹 Chore (updates to the build process or auxiliary tools and libraries) -- [ ] ⚠️ Breaking change (fix or feature that would cause existing functionality to change) + ### πŸ“š Description - - - + -### πŸ“ Checklist + - - +- Check that there isn't already a PR that solves the problem the same way. If you find a duplicate, please help us reviewing it. +- Read the contribution docs at https://nuxt.com/docs/community/contribution +- Ensure that PR title follows conventional commits (https://conventionalcommits.org) +- Update the corresponding documentation if needed. +- Include relevant tests that fail without this PR but pass with it. -- [ ] I have linked an issue or discussion. -- [ ] I have added tests (if possible). -- [ ] I have updated the documentation accordingly. +Thank you for contributing to Nuxt! +-----------------------------------------------------------------------> diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index 09e2bfd25a..ff99ac81c3 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -26,9 +26,6 @@ jobs: - name: Build (stub) run: pnpm dev:prepare - - name: Lint (code) - run: pnpm lint:fix - - name: Test (unit) run: pnpm test:unit -u @@ -52,4 +49,7 @@ jobs: if: ${{ !contains(github.head_ref, 'renovate') }} run: pnpm vitest run bundle -u + - name: Lint (code) + run: pnpm lint:fix + - uses: autofix-ci/action@ea32e3a12414e6d3183163c3424a7d7a8631ad84 diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 028a297f84..492c58ed3f 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -15,8 +15,6 @@ env: # 7 GiB by default on GitHub, setting to 6 GiB # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources NODE_OPTIONS: --max-old-space-size=6144 - # install playwright binary manually (because pnpm only runs install script once) - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1" # Remove default permissions of GITHUB_TOKEN for security # https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs @@ -48,7 +46,7 @@ jobs: run: pnpm build - name: Run benchmarks - uses: CodSpeedHQ/action@2e04019f4572c19684929a755da499f19a00b25b # v2.2.1 + uses: CodSpeedHQ/action@1dbf41f0ae41cebfe61e084e535aebe533409b4d # v2.3.0 with: run: pnpm vitest bench token: ${{ secrets.CODSPEED_TOKEN }} diff --git a/.github/workflows/changelogensets.yml b/.github/workflows/changelog.yml similarity index 96% rename from .github/workflows/changelogensets.yml rename to .github/workflows/changelog.yml index 92ad691096..515b3735e9 100644 --- a/.github/workflows/changelogensets.yml +++ b/.github/workflows/changelog.yml @@ -1,4 +1,4 @@ -name: Release +name: changelog on: push: @@ -15,7 +15,7 @@ concurrency: cancel-in-progress: ${{ github.event_name != 'push' }} jobs: - update-changelog: + update: if: github.repository_owner == 'nuxt' && !contains(github.event.head_commit.message, 'v3.') runs-on: ubuntu-latest diff --git a/.github/workflows/check-links.yml b/.github/workflows/check-links.yml index 9b8ddaff9c..d4bd197866 100644 --- a/.github/workflows/check-links.yml +++ b/.github/workflows/check-links.yml @@ -18,7 +18,7 @@ jobs: steps: # Cache lychee results (e.g. to avoid hitting rate limits) - name: Restore lychee cache - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: .lycheecache key: cache-lychee-${{ github.sha }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6f9d36556..50d8afa48b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,8 +20,6 @@ env: # 7 GiB by default on GitHub, setting to 6 GiB # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources NODE_OPTIONS: --max-old-space-size=6144 - # install playwright binary manually (because pnpm only runs install script once) - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1" # Remove default permissions of GITHUB_TOKEN for security # https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs @@ -85,19 +83,19 @@ jobs: run: pnpm install - name: Initialize CodeQL - uses: github/codeql-action/init@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 + uses: github/codeql-action/init@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 with: languages: javascript queries: +security-and-quality - name: Restore dist cache - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 with: name: dist path: packages - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 + uses: github/codeql-action/analyze@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 with: category: "/language:javascript" @@ -124,7 +122,7 @@ jobs: run: pnpm install - name: Restore dist cache - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 with: name: dist path: packages @@ -220,34 +218,11 @@ jobs: - name: Install dependencies run: pnpm install - # Install playwright's binary under custom directory to cache - - name: (non-windows) Set Playwright path and Get playwright version - if: runner.os != 'Windows' - run: | - echo "PLAYWRIGHT_BROWSERS_PATH=$HOME/.cache/playwright-bin" >> $GITHUB_ENV - PLAYWRIGHT_VERSION="$(pnpm ls --depth 0 --json -w playwright-core | jq --raw-output '.[0].devDependencies["playwright-core"].version')" - echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV - - - name: (windows) Set Playwright path and Get playwright version - if: runner.os == 'Windows' - run: | - echo "PLAYWRIGHT_BROWSERS_PATH=$HOME\.cache\playwright-bin" >> $env:GITHUB_ENV - $env:PLAYWRIGHT_VERSION="$(pnpm ls --depth 0 --json -w playwright-core | jq --raw-output '.[0].devDependencies["playwright-core"].version')" - echo "PLAYWRIGHT_VERSION=$env:PLAYWRIGHT_VERSION" >> $env:GITHUB_ENV - - - name: Cache Playwright's binary - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 - with: - key: ${{ runner.os }}-playwright-bin-v1-${{ env.PLAYWRIGHT_VERSION }} - path: ${{ env.PLAYWRIGHT_BROWSERS_PATH }} - restore-keys: | - ${{ runner.os }}-playwright-bin-v1- - - name: Install Playwright run: pnpm playwright-core install chromium - name: Restore dist cache - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 with: name: dist path: packages @@ -261,7 +236,7 @@ jobs: TEST_CONTEXT: ${{ matrix.context }} SKIP_BUNDLE_SIZE: ${{ github.event_name != 'push' || matrix.env == 'dev' || matrix.builder == 'webpack' || matrix.context == 'default' || runner.os == 'Windows' }} - - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # v4.0.2 + - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # v4.2.0 if: github.event_name != 'push' && matrix.env == 'built' && matrix.builder == 'vite' && matrix.context == 'default' && matrix.os == 'ubuntu-latest' && matrix.manifest == 'manifest-on' with: token: ${{ secrets.CODECOV_TOKEN }} @@ -296,7 +271,7 @@ jobs: run: pnpm install - name: Restore dist cache - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 with: name: dist path: packages @@ -335,7 +310,7 @@ jobs: run: pnpm install - name: Restore dist cache - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 with: name: dist path: packages diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 4537173ac3..b818d2f085 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -19,4 +19,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: 'Dependency Review' - uses: actions/dependency-review-action@9129d7d40b8c12c1ed0f60400d00c92d437adcce # v4.1.3 + uses: actions/dependency-review-action@5bbc3ba658137598168acb2ab73b21c432dd411b # v4.2.5 diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml index 778e5c454b..9d4d26a63e 100644 --- a/.github/workflows/release-pr.yml +++ b/.github/workflows/release-pr.yml @@ -1,4 +1,4 @@ -name: release +name: release-pr on: issue_comment: @@ -22,7 +22,7 @@ jobs: steps: - name: Ensure action is by maintainer - uses: octokit/request-action@89697eb6635e52c6e1e5559f15b5c91ba5100cb0 # v2.1.9 + uses: octokit/request-action@d69a4d4369a61d4045c56451421ff93ee5e7bea0 # v2.2.0 id: check_role with: route: GET /repos/nuxt/nuxt/collaborators/${{ github.event.comment.user.login }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..3aec93b443 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,40 @@ +name: release + +on: + push: + tags: + - "v*" + +# Remove default permissions of GITHUB_TOKEN for security +# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs +permissions: {} + +jobs: + release: + if: github.repository == 'nuxt/nuxt' && startsWith(github.event.head_commit.message, 'v3.') + permissions: + id-token: write + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + - run: corepack enable + - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + with: + node-version: 20 + registry-url: "https://registry.npmjs.org/" + cache: "pnpm" + + - name: Install dependencies + run: pnpm install + + - name: Build (stub) + run: pnpm dev:prepare + + - name: Release + run: ./scripts/release.sh + env: + NODE_AUTH_TOKEN: ${{secrets.RELEASE_NODE_AUTH_TOKEN}} + NPM_CONFIG_PROVENANCE: true diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 4d7d7ae87e..0284a0f22f 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -66,6 +66,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 + uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 with: sarif_file: results.sarif diff --git a/.npmrc b/.npmrc index e2ad808f8d..8fb0b90fee 100644 --- a/.npmrc +++ b/.npmrc @@ -1,3 +1,2 @@ shamefully-hoist=true -strict-peer-dependencies=false shell-emulator=true diff --git a/README.md b/README.md index 1289880ae0..5481321e39 100644 --- a/README.md +++ b/README.md @@ -13,16 +13,32 @@ Nuxt is a free and open-source framework with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with Vue.js. It provides a number of features that make it easy to build fast, SEO-friendly, and scalable web applications, including: -- Server-side rendering, Static Site Generation or Hybrid Rendering -- Automatic routing with code-splitting -- State management -- SEO Optimization -- Auto imports -- Extensible with [180+ modules](https://nuxt.com/modules) +- Server-side rendering, Static Site Generation, Hybrid Rendering and Edge-Side Rendering +- Automatic routing with code-splitting and pre-fetching +- Data fetching and state management +- SEO Optimization and Meta tags definition +- Auto imports of components, composables and utils +- TypeScript with zero configuration +- Go fullstack with our server/ directory +- Extensible with [200+ modules](https://nuxt.com/modules) - Deployment to a variety of [hosting platforms](https://nuxt.com/deploy) - ...[and much more](https://nuxt.com) πŸš€ -## Getting Started +### Table of Contents + +- πŸš€ [Getting Started](#getting-started) +- πŸ’» [ Vue Development](#vue-development) +- πŸ“– [Documentation](#documentation) +- 🧩 [Modules](#modules) +- ❀️ [Contribute](#contribute) +- 🏠 [Local Development](#local-development) +- ⛰️ [Nuxt 2](#nuxt-2) +- πŸ”— [Follow us](#follow-us) +- βš–οΈ [License](#license) + +--- + +## πŸš€ Getting Started Use the following command to create a new starter project. This will create a starter project with all the necessary files and dependencies: @@ -30,9 +46,10 @@ Use the following command to create a new starter project. This will create a st npx nuxi@latest init ``` -Discover also [nuxt.new](https://nuxt.new): Open a Nuxt starter on CodeSandbox, StackBlitz or locally to get up and running in a few seconds. +> [!TIP] +> Discover also [nuxt.new](https://nuxt.new): Open a Nuxt starter on CodeSandbox, StackBlitz or locally to get up and running in a few seconds. -## Vue Development +## πŸ’» Vue Development Simple, intuitive and powerful, Nuxt lets you write Vue components in a way that makes sense. Every repetitive task is automated, so you can focus on writing your full-stack Vue application with confidence. @@ -54,7 +71,7 @@ useSeoMeta({ - ``` -## Documentation +## πŸ“– Documentation We highly recommend you take a look at the [Nuxt documentation](https://nuxt.com/docs) to level up. It’s a great resource for learning more about the framework. It covers everything from getting started to advanced topics. -## Modules +## 🧩 Modules Discover our [list of modules](https://nuxt.com/modules) to supercharge your Nuxt project, created by the Nuxt team and community. -## Contribute +## ❀️ Contribute We invite you to contribute and help improve Nuxt πŸ’š @@ -79,21 +96,20 @@ Here are a few ways you can get involved: - **Suggestions:** Have ideas to enhance Nuxt? We'd love to hear them! Check out the [contribution guide](https://nuxt.com/docs/community/contribution#creating-an-issue) to share your suggestions. - **Questions:** If you have questions or need assistance, the [getting help guide](https://nuxt.com/docs/community/getting-help) provides resources to help you out. -## Local Development +## 🏠 Local Development Follow the docs to [Set Up Your Local Development Environment](https://nuxt.com/docs/community/framework-contribution#setup) to contribute to the framework and documentation. -## Nuxt 2 +## ⛰️ Nuxt 2 You can find the code for Nuxt 2 on the [`2.x` branch](https://github.com/nuxt/nuxt/tree/2.x) and the documentation at [v2.nuxt.com](https://v2.nuxt.com). -## Follow us +## πŸ”— Follow us

Discord  Twitter  GitHub

-## License +## βš–οΈ License [MIT](./LICENSE) - diff --git a/docs/1.getting-started/11.testing.md b/docs/1.getting-started/11.testing.md index 2051ded616..729b830bea 100644 --- a/docs/1.getting-started/11.testing.md +++ b/docs/1.getting-started/11.testing.md @@ -15,8 +15,8 @@ Nuxt offers first-class support for end-to-end and unit testing of your Nuxt app In order to allow you to manage your other testing dependencies, `@nuxt/test-utils` ships with various optional peer dependencies. For example: - you can choose between `happy-dom` and `jsdom` for a runtime Nuxt environment -- you can choose between `vitest` and `jest` for end-to-end test runners -- `playwright-core` is only required if you wish to use the built-in browser testing utilities +- you can choose between `vitest`, `cucumber`, `jest` and `playwright` for end-to-end test runners +- `playwright-core` is only required if you wish to use the built-in browser testing utilities (and are not using `@playwright/test` as your test runner) ::code-group ```bash [yarn] @@ -88,6 +88,7 @@ export default defineVitestConfig({ // environmentOptions: { // nuxt: { // rootDir: fileURLToPath(new URL('./playground', import.meta.url)), + // domEnvironment: 'happy-dom', // 'happy-dom' (default) or 'jsdom' // overrides: { // // other Nuxt config you want to pass // } @@ -387,7 +388,7 @@ await setup({ ## End-To-End Testing -For end-to-end testing, we support [Vitest](https://github.com/vitest-dev/vitest) and [Jest](https://jestjs.io) as test runners. +For end-to-end testing, we support [Vitest](https://github.com/vitest-dev/vitest), [Jest](https://jestjs.io), [Cucumber](https://cucumber.io/) and [Playwright](https://playwright.dev/) as test runners. ### Setup @@ -453,7 +454,7 @@ Please use the options below for the `setup` method. - `type`: The type of browser to launch - either `chromium`, `firefox` or `webkit` - `launch`: `object` of options that will be passed to playwright when launching the browser. See [full API reference](https://playwright.dev/docs/api/class-browsertype#browser-type-launch). - `runner`: Specify the runner for the test suite. Currently, [Vitest](https://vitest.dev) is recommended. - - Type: `'vitest' | 'jest'` + - Type: `'vitest' | 'jest' | 'cucumber'` - Default: `'vitest'` ### APIs @@ -492,11 +493,11 @@ const pageUrl = url('/page') ### Testing in a Browser -We provide built-in support using Playwright within `@nuxt/test-utils`, but you can also use other test runners for end-to-end browser testing. +We provide built-in support using Playwright within `@nuxt/test-utils`, either programmatically or via the Playwright test runner. #### `createPage(url)` -You can create a configured Playwright browser instance, and (optionally) point it at a path from the running server. You can find out more about the API methods available from [in the Playwright documentation](https://playwright.dev/docs/api/class-page). +Within `vitest`, `jest` or `cucumber`, you can create a configured Playwright browser instance with `createPage`, and (optionally) point it at a path from the running server. You can find out more about the API methods available from [in the Playwright documentation](https://playwright.dev/docs/api/class-page). ```ts twoslash import { createPage } from '@nuxt/test-utils/e2e' @@ -504,3 +505,70 @@ import { createPage } from '@nuxt/test-utils/e2e' const page = await createPage('/page') // you can access all the Playwright APIs from the `page` variable ``` + +#### Testing with Playwright Test Runner + +We also provide first-class support for testing Nuxt within [the Playwright test runner](https://playwright.dev/docs/intro). + +::code-group +```bash [yarn] +yarn add --dev @playwright/test @nuxt/test-utils +``` +```bash [npm] +npm i --save-dev @playwright/test @nuxt/test-utils +``` +```bash [pnpm] +pnpm add -D @playwright/test @nuxt/test-utils +``` +```bash [bun] +bun add --dev @playwright/test @nuxt/test-utils +``` +:: + +You can provide global Nuxt configuration, with the same configuration details as the `setup()` function mentioned earlier in this section. + +```ts [playwright.config.ts] +import { fileURLToPath } from 'node:url' +import { defineConfig, devices } from '@playwright/test' +import type { ConfigOptions } from '@nuxt/test-utils/playwright' + +export default defineConfig({ + use: { + nuxt: { + rootDir: fileURLToPath(new URL('.', import.meta.url)) + } + }, + // ... +}) +``` + +::read-more{title="See full example config" to="https://github.com/nuxt/test-utils/blob/main/examples/app-playwright/playwright.config.ts" target="_blank"} +:: + +Your test file should then use `expect` and `test` directly from `@nuxt/test-utils/playwright`: + +```ts [tests/example.test.ts] +import { expect, test } from '@nuxt/test-utils/playwright' + +test('test', async ({ page, goto }) => { + await goto('/', { waitUntil: 'hydration' }) + await expect(page.getByRole('heading')).toHaveText('Welcome to Playwright!') +}) +``` + +You can alternatively configure your Nuxt server directly within your test file: + +```ts [tests/example.test.ts] +import { expect, test } from '@nuxt/test-utils/playwright' + +test.use({ + nuxt: { + rootDir: fileURLToPath(new URL('..', import.meta.url)) + } +}) + +test('test', async ({ page, goto }) => { + await goto('/', { waitUntil: 'hydration' }) + await expect(page.getByRole('heading')).toHaveText('Welcome to Playwright!') +}) +``` diff --git a/docs/1.getting-started/2.installation.md b/docs/1.getting-started/2.installation.md index f7a4d317ac..f89438e8f2 100644 --- a/docs/1.getting-started/2.installation.md +++ b/docs/1.getting-started/2.installation.md @@ -22,7 +22,7 @@ Start with one of our starters and themes directly by opening [nuxt.new](https:/ #### Prerequisites - **Node.js** - [`v18.0.0`](https://nodejs.org/en) or newer -- **Text editor** - We recommend [Visual Studio Code](https://code.visualstudio.com/) with the [Volar Extension](https://marketplace.visualstudio.com/items?itemName=Vue.volar) +- **Text editor** - We recommend [Visual Studio Code](https://code.visualstudio.com/) with the [official Vue extension](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (previously known as Volar) - **Terminal** - In order to run Nuxt commands ::note @@ -30,17 +30,6 @@ Start with one of our starters and themes directly by opening [nuxt.new](https:/ :summary[Additional notes for an optimal setup:] - **Node.js**: Make sure to use an even numbered version (18, 20, etc) - **Nuxtr**: Install the community-developed [Nuxtr extension](https://marketplace.visualstudio.com/items?itemName=Nuxtr.nuxtr-vscode) - - **Volar**: Either enable [**Take Over Mode**](https://vuejs.org/guide/typescript/overview.html#volar-takeover-mode) (recommended) or add the [TypeScript Vue Plugin](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) - - If you have enabled **Take Over Mode** or installed the **TypeScript Vue Plugin (Volar)**, you can disable generating the shim for `*.vue` files in your [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt-config) file: - - ```ts twoslash [nuxt.config.ts] - export default defineNuxtConfig({ - typescript: { - shim: false - } - }) - ``` :: :: diff --git a/docs/1.getting-started/4.styling.md b/docs/1.getting-started/4.styling.md index b2437a9cef..4b2bd3be36 100644 --- a/docs/1.getting-started/4.styling.md +++ b/docs/1.getting-started/4.styling.md @@ -243,7 +243,7 @@ Nuxt uses Vite by default. If you wish to use webpack instead, refer to each pre ## Single File Components (SFC) Styling -One of the best things about Vue and SFC is how great it is at naturally dealing with styling. You can directly write CSS or preprocessor code in the style block of your components file, therefore you will have fantastic developer experience without having to use something like CSS-in-JS. However if you wish to use CSS-in-JS, you can find 3rd party libraries and modules that support it, such as [pinceau](https://pinceau.dev). +One of the best things about Vue and SFC is how great it is at naturally dealing with styling. You can directly write CSS or preprocessor code in the style block of your components file, therefore you will have fantastic developer experience without having to use something like CSS-in-JS. However if you wish to use CSS-in-JS, you can find 3rd party libraries and modules that support it, such as [pinceau](https://github.com/Tahul/pinceau). You can refer to the [Vue docs](https://vuejs.org/api/sfc-css-features.html) for a comprehensive reference about styling components in SFC. @@ -421,7 +421,7 @@ For proper syntax highlighting in SFC, you can use the postcss lang attribute. ```vue ``` @@ -430,7 +430,7 @@ By default, Nuxt comes with the following plugins already pre-configured: - [postcss-import](https://github.com/postcss/postcss-import): Improves the `@import` rule - [postcss-url](https://github.com/postcss/postcss-url): Transforms `url()` statements - [autoprefixer](https://github.com/postcss/autoprefixer): Automatically adds vendor prefixes -- [cssnano](https://cssnano.co): Minification and purge +- [cssnano](https://cssnano.github.io/cssnano): Minification and purge ## Leveraging Layouts For Multiple Styles @@ -458,14 +458,14 @@ Use different styles for different layouts. Nuxt isn't opinionated when it comes to styling and provides you with a wide variety of options. You can use any styling tool that you want, such as popular libraries like [UnoCSS](https://unocss.dev) or [Tailwind CSS](https://tailwindcss.com). -The community and the Nuxt team have developed plenty of Nuxt modules to makes the integration easier. +The community and the Nuxt team have developed plenty of Nuxt modules to make the integration easier. You can discover them on the [modules section](/modules) of the website. Here are a few modules to help you get started: - [UnoCSS](/modules/unocss): Instant on-demand atomic CSS engine - [Tailwind CSS](/modules/tailwindcss): Utility-first CSS framework - [Fontaine](https://github.com/nuxt-modules/fontaine): Font metric fallback -- [Pinceau](https://pinceau.dev): Adaptable styling framework +- [Pinceau](https://github.com/Tahul/pinceau): Adaptable styling framework - [Nuxt UI](https://ui.nuxt.com): A UI Library for Modern Web Apps - [Panda CSS](https://panda-css.com/docs/installation/nuxt): CSS-in-JS engine that generates atomic CSS at build time diff --git a/docs/1.getting-started/5.seo-meta.md b/docs/1.getting-started/5.seo-meta.md index e77839558d..a1ebb2f457 100644 --- a/docs/1.getting-started/5.seo-meta.md +++ b/docs/1.getting-started/5.seo-meta.md @@ -6,7 +6,7 @@ navigation.icon: i-ph-file-search-duotone ## Defaults -Out-of-the-box, Nuxt provides sane defaults, which you can override if needed. +Out-of-the-box, Nuxt provides sensible defaults, which you can override if needed. ```ts twoslash [nuxt.config.ts] export default defineNuxtConfig({ @@ -174,7 +174,7 @@ You can use the `titleTemplate` option to provide a dynamic template for customi The `titleTemplate` can either be a string, where `%s` is replaced with the title, or a function. -If you want to use a function (for full control), then this cannot be set in your `nuxt.config`, and it is recommended instead to set it within your `app.vue` file, where it will apply to all pages on your site: +If you want to use a function (for full control), then this cannot be set in your `nuxt.config`. It is recommended instead to set it within your `app.vue` file where it will apply to all pages on your site: ::code-group diff --git a/docs/1.getting-started/6.data-fetching.md b/docs/1.getting-started/6.data-fetching.md index 3e1cf5cd02..b6b52457c9 100644 --- a/docs/1.getting-started/6.data-fetching.md +++ b/docs/1.getting-started/6.data-fetching.md @@ -60,7 +60,7 @@ This composable is a wrapper around the [`useAsyncData`](/docs/api/composables/u ## `$fetch` -Nuxt includes the `ofetch` library, and is auto-imported as the `$fetch` alias globally across your application. It's what `useFetch` uses behind the scenes. +Nuxt includes the [ofetch](https://github.com/unjs/ofetch) library, and is auto-imported as the `$fetch` alias globally across your application. It's what `useFetch` uses behind the scenes. ```vue twoslash [pages/todos.vue] +``` + #### Watch To re-run your fetching function each time other reactive values in your application change, use the `watch` option. You can use it for one or multiple _watchable_ elements. diff --git a/docs/1.getting-started/7.state-management.md b/docs/1.getting-started/7.state-management.md index 1f58ce72c5..d9edf3f161 100644 --- a/docs/1.getting-started/7.state-management.md +++ b/docs/1.getting-started/7.state-management.md @@ -130,12 +130,12 @@ export const useLocale = () => { export const useDefaultLocale = (fallback = 'en-US') => { const locale = ref(fallback) - if (process.server) { + if (import.meta.server) { const reqLocale = useRequestHeaders()['accept-language']?.split(',')[0] if (reqLocale) { locale.value = reqLocale } - } else if (process.client) { + } else if (import.meta.client) { const navLang = navigator.language if (navLang) { locale.value = navLang @@ -192,7 +192,6 @@ const date = useLocaleDate(new Date('2016-10-26')) By using [auto-imported composables](/docs/guide/directory-structure/composables) we can define global type-safe states and import them across the app. ```ts twoslash [composables/states.ts] -export const useCounter = () => useState('counter', () => 0) export const useColor = () => useState('color', () => 'pink') ``` diff --git a/docs/1.getting-started/8.error-handling.md b/docs/1.getting-started/8.error-handling.md index 7ede474f2f..e3b944dbc6 100644 --- a/docs/1.getting-started/8.error-handling.md +++ b/docs/1.getting-started/8.error-handling.md @@ -7,15 +7,15 @@ navigation.icon: i-ph-bug-beetle-duotone Nuxt 3 is a full-stack framework, which means there are several sources of unpreventable user runtime errors that can happen in different contexts: - Errors during the Vue rendering lifecycle (SSR & CSR) -- Errors during Nitro server lifecycle ([`server/`](/docs/guide/directory-structure/server) directory) - Server and client startup errors (SSR + CSR) +- Errors during Nitro server lifecycle ([`server/`](/docs/guide/directory-structure/server) directory) - Errors downloading JS chunks ::tip **SSR** stands for **Server-Side Rendering** and **CSR** for **Client-Side Rendering**. :: -## Vue Rendering Lifecycle +## Vue Errors You can hook into Vue errors using [`onErrorCaptured`](https://vuejs.org/api/composition-api-lifecycle.html#onerrorcaptured). @@ -51,7 +51,7 @@ This includes: - mounting the app (on client-side), though you should handle this case with `onErrorCaptured` or with `vue:error` - processing the `app:mounted` hook -## Nitro Server Lifecycle +## Nitro Server Errors You cannot currently define a server-side handler for these errors, but can render an error page, see the [Render an Error Page](#error-page) section. diff --git a/docs/1.getting-started/8.server.md b/docs/1.getting-started/8.server.md index 94e2da9e7c..49e0f21464 100644 --- a/docs/1.getting-started/8.server.md +++ b/docs/1.getting-started/8.server.md @@ -83,9 +83,9 @@ export default defineNuxtConfig({ Learn about all available route rules are available to customize the rendering mode of your routes. :: -In addition, there are some route rules (for example, `ssr` and `experimentalNoScripts`) that are Nuxt specific to change the behavior when rendering your pages to HTML. +In addition, there are some route rules (for example, `ssr`, `appMiddleware`, and `experimentalNoScripts`) that are Nuxt specific to change the behavior when rendering your pages to HTML. -Some route rules (`redirect` and `prerender`) also affect client-side behavior. +Some route rules (`appMiddleware`, `redirect` and `prerender`) also affect client-side behavior. Nitro is used to build the app for server side rendering, as well as pre-rendering. diff --git a/docs/1.getting-started/9.layers.md b/docs/1.getting-started/9.layers.md index ed61136af1..1ae3f05d79 100644 --- a/docs/1.getting-started/9.layers.md +++ b/docs/1.getting-started/9.layers.md @@ -14,12 +14,13 @@ One of the core features of Nuxt 3 is the layers and extending support. You can - Create Nuxt module presets - Share standard setup across projects - Create Nuxt themes +- Enhance code organization by implementing a modular architecture and support Domain-Driven Design (DDD) pattern in large scale projects. ## Usage You can extend a layer by adding the [extends](/docs/api/nuxt-config#extends) property to the [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt-config) file. -```ts twoslash [nuxt.config.ts] +```ts [nuxt.config.ts] export default defineNuxtConfig({ extends: [ '../base', // Extend from a local layer @@ -29,6 +30,19 @@ export default defineNuxtConfig({ }) ``` +You can also pass an authentication token if you are extending from a private GitHub repository: + +```ts [nuxt.config.ts] +export default defineNuxtConfig({ + extends: [ + // per layer configuration + ['github:my-themes/private-awesome', { auth: process.env.GITHUB_TOKEN }] + ] +}) +``` + +Nuxt uses [unjs/c12](https://c12.unjs.io) and [unjs/giget](https://giget.unjs.io) for extending remote layers. Check the documentation for more information and all available options. + ::read-more{to="/docs/guide/going-further/layers"} Read more about layers in the **Layer Author Guide**. :: diff --git a/docs/2.guide/1.concepts/1.auto-imports.md b/docs/2.guide/1.concepts/1.auto-imports.md index b26265d3c6..0fd8a3b63f 100644 --- a/docs/2.guide/1.concepts/1.auto-imports.md +++ b/docs/2.guide/1.concepts/1.auto-imports.md @@ -84,7 +84,7 @@ export const useMyComposable = () => { ```ts twoslash [composables/example.ts] export const useMyComposable = () => { // Because your composable is called in the right place in the lifecycle, - // useRuntimeConfig will also work + // useRuntimeConfig will work here const config = useRuntimeConfig() // ... diff --git a/docs/2.guide/1.concepts/3.rendering.md b/docs/2.guide/1.concepts/3.rendering.md index 3c4fa6ca56..4adf1baaab 100644 --- a/docs/2.guide/1.concepts/3.rendering.md +++ b/docs/2.guide/1.concepts/3.rendering.md @@ -109,10 +109,11 @@ The different properties you can use are the following: - `ssr: boolean`{lang=ts} - Disables server-side rendering for sections of your app and make them SPA-only with `ssr: false` - `cors: boolean`{lang=ts} - Automatically adds cors headers with `cors: true` - you can customize the output by overriding with `headers` - `headers: object`{lang=ts} - Add specific headers to sections of your site - for example, your assets -- `swr: number|boolean`{lang=ts} - Add cache headers to the server response and cache it on the server or reverse proxy for a configurable TTL (time to live). The `node-server` preset of Nitro is able to cache the full response. When the TTL expired, the cached response will be sent while the page will be regenerated in the background. If true is used, a `stale-while-revalidate` header is added without a MaxAge. -- `isr: number|boolean`{lang=ts} - The behavior is the same as `swr` except that we are able to add the response to the CDN cache on platforms that support this (currently Netlify or Vercel). If `true` is used, the content persists until the next deploy inside the CDN. -- `prerender:boolean`{lang=ts} - Prerenders routes at build time and includes them in your build as static assets +- `swr: number | boolean`{lang=ts} - Add cache headers to the server response and cache it on the server or reverse proxy for a configurable TTL (time to live). The `node-server` preset of Nitro is able to cache the full response. When the TTL expired, the cached response will be sent while the page will be regenerated in the background. If true is used, a `stale-while-revalidate` header is added without a MaxAge. +- `isr: number | boolean`{lang=ts} - The behavior is the same as `swr` except that we are able to add the response to the CDN cache on platforms that support this (currently Netlify or Vercel). If `true` is used, the content persists until the next deploy inside the CDN. +- `prerender: boolean`{lang=ts} - Prerenders routes at build time and includes them in your build as static assets - `experimentalNoScripts: boolean`{lang=ts} - Disables rendering of Nuxt scripts and JS resource hints for sections of your site. +- `appMiddleware: string | string[] | Record`{lang=ts} - Allows you to define middleware that should or should not run for page paths within the Vue app part of your application (that is, not your Nitro routes) Whenever possible, route rules will be automatically applied to the deployment platform's native rules for optimal performances (Netlify and Vercel are currently supported). diff --git a/docs/2.guide/1.concepts/8.typescript.md b/docs/2.guide/1.concepts/8.typescript.md index e2718dc55f..afc7ae5a05 100644 --- a/docs/2.guide/1.concepts/8.typescript.md +++ b/docs/2.guide/1.concepts/8.typescript.md @@ -9,22 +9,26 @@ By default, Nuxt doesn't check types when you run [`nuxi dev`](/docs/api/command To enable type-checking at build or development time, install `vue-tsc` and `typescript` as development dependency: +::alert{type="warning"} +You may experience issues with the latest `vue-tsc` and `vite-plugin-checker`, used internally when type checking. For now, you may need to stay on v1 of `vue-tsc`, and follow these upstream issues for updates: [fi3ework/vite-plugin-checker#306](https://github.com/fi3ework/vite-plugin-checker/issues/306) and [vuejs/language-tools#3969](https://github.com/vuejs/language-tools/issues/3969). +:: + ::code-group ```bash [yarn] - yarn add --dev vue-tsc typescript + yarn add --dev vue-tsc@^1 typescript ``` ```bash [npm] - npm install --save-dev vue-tsc typescript + npm install --save-dev vue-tsc@^1 typescript ``` ```bash [pnpm] - pnpm add -D vue-tsc typescript + pnpm add -D vue-tsc@^1 typescript ``` ```bash [bun] - bun add -D vue-tsc typescript + bun add -D vue-tsc@^1 typescript ``` :: diff --git a/docs/2.guide/2.directory-structure/1.components.md b/docs/2.guide/2.directory-structure/1.components.md index 929d2b6a42..0685a3389c 100644 --- a/docs/2.guide/2.directory-structure/1.components.md +++ b/docs/2.guide/2.directory-structure/1.components.md @@ -244,6 +244,10 @@ This feature only works with Nuxt auto-imports and `#components` imports. Explic `.client` components are rendered only after being mounted. To access the rendered template using `onMounted()`, add `await nextTick()` in the callback of the `onMounted()` hook. :: +::read-more{to="/docs/api/components/client-only"} +You can also achieve a similar result with the `` component. +:: + ## Server Components Server components allow server-rendering individual components within your client-side apps. It's possible to use server components within Nuxt, even if you are generating a static site. That makes it possible to build complex sites that mix dynamic components, server-rendered HTML and even static chunks of markup. @@ -295,6 +299,14 @@ Now you can register server-only components with the `.server` suffix and use th Server-only components use [``](/docs/api/components/nuxt-island) under the hood, meaning that `lazy` prop and `#fallback` slot are both passed down to it. +::alert{type=warning} +Server components (and islands) must have a single root element. (HTML comments are considered elements as well.) +:: + +::alert{type=warning} +Most features for server-only components and island components, such as slots and client components, are only available for single file components. +:: + #### Client components within server components ::alert{type=info} @@ -314,7 +326,7 @@ You can partially hydrate a component by setting a `nuxt-client` attribute on th ``` ::alert{type=info} -This only works within a server component.Β Slots for client components are not available yet. +This only works within a server component.Β Slots for client components are working only with `experimental.componentIsland.selectiveClient` set to `'deep'` and since they are rendered server-side, they are not interactive once client-side. :: #### Server Component Context @@ -353,89 +365,12 @@ In this case, the `.server` + `.client` components are two 'halves' of a compone ``` -## `` Component +## Built-In Nuxt Components -Nuxt provides the [``](/docs/api/components/client-only) component for purposely rendering a component only on client side. +There are a number of components that Nuxt provides, including `` and ``. You can read more about them in the API documentation. -```vue [pages/example.vue] - -``` - -Use a slot as fallback until `` is mounted on client side. - -```vue [pages/example.vue] - -``` - - - - -## `` Component - -Nuxt provides the `` component to render a component only during development. - -The content will not be included in production builds and tree-shaken. - -```vue [pages/example.vue] - -``` - -## `` Component - -Nuxt provides the `` component to render its content on the client if any of its children trigger an error in SSR. -You can specify a `fallbackTag` to make it render a specific tag if it fails to render on the server. - -```vue [pages/example.vue] - -``` ## Library Authors diff --git a/docs/2.guide/2.directory-structure/1.middleware.md b/docs/2.guide/2.directory-structure/1.middleware.md index 22c63eb24a..e4e97484d3 100644 --- a/docs/2.guide/2.directory-structure/1.middleware.md +++ b/docs/2.guide/2.directory-structure/1.middleware.md @@ -125,12 +125,12 @@ However, if you want to avoid this behaviour you can do so: ```ts twoslash [middleware/example.ts] export default defineNuxtRouteMiddleware(to => { // skip middleware on server - if (process.server) return + if (import.meta.server) return // skip middleware on client side entirely - if (process.client) return + if (import.meta.client) return // or only skip middleware on initial client load const nuxtApp = useNuxtApp() - if (process.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return + if (import.meta.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return }) ``` diff --git a/docs/2.guide/2.directory-structure/1.modules.md b/docs/2.guide/2.directory-structure/1.modules.md index b98df654e6..2664e5601e 100644 --- a/docs/2.guide/2.directory-structure/1.modules.md +++ b/docs/2.guide/2.directory-structure/1.modules.md @@ -56,3 +56,7 @@ modules/ ``` :read-more{to="/docs/guide/going-further/modules"} + +::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/creating-your-first-module-from-scratch" target="_blank"} +Watch Vue School video about Nuxt private modules. +:: diff --git a/docs/2.guide/2.directory-structure/1.pages.md b/docs/2.guide/2.directory-structure/1.pages.md index 2332295f8a..6ebd687bb1 100644 --- a/docs/2.guide/2.directory-structure/1.pages.md +++ b/docs/2.guide/2.directory-structure/1.pages.md @@ -57,7 +57,7 @@ If you are using [`app.vue`](/docs/guide/directory-structure/app), make sure to ``` -Pages **must have a single root element** to allow [route transitions](/docs/getting-started/transitions) between pages, HTML comments are considered elements as well. +Pages **must have a single root element** to allow [route transitions](/docs/getting-started/transitions) between pages. HTML comments are considered elements as well. This means that when the route is server-rendered, or statically generated, you will be able to see its contents correctly, but when you navigate towards that route during client-side navigation the transition between routes will fail and you'll see that the route will not be rendered. @@ -357,12 +357,16 @@ function navigate(){ ``` +## Client-Only Pages + +You can define a page as [client only](/docs/guide/directory-structure/components#client-components) by giving it a `.client.vue` suffix. None of the content of this page will be rendered on the server. + ## Server-Only Pages You can define a page as [server only](/docs/guide/directory-structure/components#server-components) by giving it a `.server.vue` suffix. While you will be able to navigate to the page using client-side navigation, controlled by `vue-router`, it will be rendered with a server component automatically, meaning the code required to render the page will not be in your client-side bundle. -::note -You will also need to enable `experimental.componentIslands` in order to make this possible. +::alert{type=warning} +Server-only pages must have a single root element. (HTML comments are considered elements as well.) :: ## Custom Routing diff --git a/docs/2.guide/2.directory-structure/1.plugins.md b/docs/2.guide/2.directory-structure/1.plugins.md index 995e6212d1..4de600585d 100644 --- a/docs/2.guide/2.directory-structure/1.plugins.md +++ b/docs/2.guide/2.directory-structure/1.plugins.md @@ -78,7 +78,7 @@ export default defineNuxtPlugin({ ::note If you are using the object-syntax, the properties may be statically analyzed in future to produce a more optimized build. So you should not define them at runtime. :br -For example, setting `enforce: process.server ? 'pre' : 'post'` would defeat any future optimization Nuxt is able to do for your plugins. +For example, setting `enforce: import.meta.server ? 'pre' : 'post'` would defeat any future optimization Nuxt is able to do for your plugins. :: ## Registration Order diff --git a/docs/2.guide/2.directory-structure/3.app-config.md b/docs/2.guide/2.directory-structure/3.app-config.md index d8eb2ce4be..93c15381f8 100644 --- a/docs/2.guide/2.directory-structure/3.app-config.md +++ b/docs/2.guide/2.directory-structure/3.app-config.md @@ -99,7 +99,7 @@ Nuxt uses a custom merging strategy for the `AppConfig` within [the layers](/doc This strategy is implemented using a [Function Merger](https://github.com/unjs/defu#function-merger), which allows defining a custom merging strategy for every key in `app.config` that has an array as value. ::note -The Function Merger should only be used in the base `app.config` of your application. +The function merger can only be used in the extended layers and not the main `app.config` in project. :: Here's an example of how you can use: diff --git a/docs/2.guide/3.going-further/10.runtime-config.md b/docs/2.guide/3.going-further/10.runtime-config.md index f4ca19cd94..e84823704c 100644 --- a/docs/2.guide/3.going-further/10.runtime-config.md +++ b/docs/2.guide/3.going-further/10.runtime-config.md @@ -98,7 +98,7 @@ The behavior is different between the client-side and server-side: const config = useRuntimeConfig() console.log('Runtime config:', config) -if (process.server) { +if (import.meta.server) { console.log('API secret:', config.apiSecret) } @@ -164,3 +164,7 @@ declare module 'nuxt/schema' { // It is always important to ensure you import/export something when augmenting a type export {} ``` + +::note +`nuxt/schema` is provided as a convenience for end-users to access the version of the schema used by Nuxt in their project. Module authors should instead augment `@nuxt/schema`. +:: diff --git a/docs/2.guide/3.going-further/3.modules.md b/docs/2.guide/3.going-further/3.modules.md index f7eae0f03f..3eb0d0d424 100644 --- a/docs/2.guide/3.going-further/3.modules.md +++ b/docs/2.guide/3.going-further/3.modules.md @@ -30,6 +30,10 @@ This will create a `my-module` project with all the boilerplate necessary to dev Learn how to perform basic tasks with the module starter. +::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/navigating-the-official-starter-template" target="_blank"} +Watch Vue School video about Nuxt module starter template. +:: + #### How to Develop While your module source code lives inside the `src` directory, in most cases, to develop a module, you need a Nuxt application. That's what the `playground` directory is about. It's a Nuxt application you can tinker with that is already configured to run with your module. @@ -255,6 +259,10 @@ export default defineNuxtModule({ When you need to handle more complex configuration alterations, you should consider using [defu](https://github.com/unjs/defu). +::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/extending-and-altering-nuxt-configuration-and-options" target="_blank"} +Watch Vue School video about altering Nuxt configuration. +:: + #### Exposing Options to Runtime Because modules aren't part of the application runtime, their options aren't either. However, in many cases, you might need access to some of these module options within your runtime code. We recommend exposing the needed config using Nuxt's [`runtimeConfig`](/docs/api/nuxt-config#runtimeconfig). @@ -288,6 +296,10 @@ Be careful not to expose any sensitive module configuration on the public runtim :read-more{to="/docs/guide/going-further/runtime-config"} +::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/passing-and-exposing-module-options" target="_blank"} +Watch Vue School video about passing and exposing Nuxt module options. +:: + #### Injecting Plugins With `addPlugin` Plugins are a common way for a module to add runtime logic. You can use the `addPlugin` utility to register them from your module. @@ -511,6 +523,10 @@ export default defineNuxtModule({ :read-more{to="/docs/api/advanced/hooks"} +::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/nuxt-lifecycle-hooks" target="_blank"} +Watch Vue School video about using Nuxt lifecycle hooks in modules. +:: + ::note **Module cleanup** :br @@ -733,6 +749,10 @@ The module starter comes with a default set of tools and configurations (e.g. ES [Nuxt Module ecosystem](/modules) represents more than 15 million monthly NPM downloads and provides extended functionalities and integrations with all sort of tools. You can be part of this ecosystem! +::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/exploring-nuxt-modules-ecosystem-and-module-types" target="_blank"} +Watch Vue School video about Nuxt module types. +:: + ### Module Types **Official modules** are modules prefixed (scoped) with `@nuxt/` (e.g. [`@nuxt/content`](https://content.nuxtjs.org)). They are made and maintained actively by the Nuxt team. Like with the framework, contributions from the community are more than welcome to help make them better! diff --git a/docs/2.guide/3.going-further/8.custom-routing.md b/docs/2.guide/3.going-further/8.custom-routing.md index b8f39b048d..b3e408c2a3 100644 --- a/docs/2.guide/3.going-further/8.custom-routing.md +++ b/docs/2.guide/3.going-further/8.custom-routing.md @@ -105,7 +105,7 @@ export default defineNuxtConfig({ const resolver = createResolver(import.meta.url) // add a route files.push({ - path: resolver.resolve('./runtime/app/router-options') + path: resolver.resolve('./runtime/app/router-options'), optional: true }) } @@ -172,6 +172,6 @@ import { createMemoryHistory } from 'vue-router' export default { // https://router.vuejs.org/api/interfaces/routeroptions.html - history: base => process.client ? createMemoryHistory(base) : null /* default */ + history: base => import.meta.client ? createMemoryHistory(base) : null /* default */ } ``` diff --git a/docs/2.guide/3.going-further/9.debugging.md b/docs/2.guide/3.going-further/9.debugging.md index 0771c6d959..59558ba67d 100644 --- a/docs/2.guide/3.going-further/9.debugging.md +++ b/docs/2.guide/3.going-further/9.debugging.md @@ -38,6 +38,10 @@ It is possible to debug your Nuxt app in your IDE while you are developing it. You may need to update the config below with a path to your web browser. For more information, visit the [VS Code documentation about debug configuration](https://go.microsoft.com/fwlink/?linkid=830387). +::important +If you use `pnpm`, you will need to have `nuxi` installed as a devDependency for the configuration below to work. +:: + ```json5 { // Use IntelliSense to learn about possible attributes. diff --git a/docs/3.api/1.components/1.client-only.md b/docs/3.api/1.components/1.client-only.md index 481ab8ab9c..86e56d2547 100644 --- a/docs/3.api/1.components/1.client-only.md +++ b/docs/3.api/1.components/1.client-only.md @@ -8,7 +8,11 @@ links: size: xs --- -The `` component renders its slot only in client-side. To import a component only on the client, register the component in a client-side only plugin. +The `` component is used for purposely rendering a component only on client side. + +::note +The content of the default slot will be tree-shaken out of the server build. (This does mean that any CSS used by components within it may not be inlined when rendering the initial HTML.) +:: ## Props @@ -19,6 +23,7 @@ The `` component renders its slot only in client-side. To import a c