Nuxt.js: Page Middleware not working in Class Styled Component in TypeScript

Created on 3 Apr 2019  路  6Comments  路  Source: nuxt/nuxt.js

Version

v2.5.1

Reproduction link

https://github.com/envision/nuxt-middleware-ts-class-bug

Steps to reproduce

npx create-nuxt-app nuxt-middleware-ts-class-bug

? Project name nuxt-middleware-ts-class-bug
? Project description Reproducing Nuxt bug with middleware not applied to class style page component
? Use a custom server framework none
? Choose features to install (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Use a custom UI framework none
? Use a custom test framework none
? Choose rendering mode Universal
? Author name Janne Kurkinen
? Choose a package manager yarn

cd nuxt-middleware-ts-class-bug

Add a new file middleware/vanilla.js:

export default function() {
  console.log('Middleware: testing vanilla')
}

In pages/index.vue, apply middleware so that the single file component's script section looks like this:

<script>
import Logo from '~/components/Logo.vue'

export default {
  components: {
    Logo
  },
  middleware: ['vanilla']
}
</script>

Run yarn dev

Open the browser and verify that 'Middleware: testing vanilla' has been logged to console after visiting the page.

Good, middleware working in JS. Then lets change to TypeScript...

Add a new file under project root tsconfig.json:

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "lib": [
      "esnext",
      "esnext.asynciterable",
      "dom"
    ],
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "allowJs": true,
    "sourceMap": true,
    "strict": true,
    "noImplicitAny": false,
    "noEmit": true,
    "baseUrl": ".",
    "paths": {
      "~/*": [
        "./*"
      ],
      "@/*": [
        "./*"
      ]
    },
    "types": [
      "@types/node",
      "@nuxt/vue-app"
    ]
  }
}

Run yarn add -D @nuxt/typescript nuxt-property-decorator

Add a new file middleware/typescript.ts:

export default context => {
  console.log('Middleware: typescript testing');
};

In pages/index.vue change the middleware name from 'vanilla' to 'typescript'.

Run yarn dev and verify again that 'Middleware: typescript testing' is logged after visiting the page.

Now change `pages/index.vue麓 script section to implement an exported class component:

<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator';

import Logo from '~/components/Logo.vue';

@Component({
  components: {
    Logo
  }
})
class Index extends Vue {

  middleware = ['typescript'];

}
export default Index;
</script>

Run in the browser and verify that no middleware gets logged...

What is expected ?

Class style page components should have middleware applied.

What is actually happening?

MIddleware gets applied to pages with object style export, but not with class style export extending Vue.

This bug report is available on Nuxt community (#c8990)
bug-report

Most helpful comment

I think this is what you want:

<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator';

import Logo from '~/components/Logo.vue';

@Component({
  components: {
    Logo
  },
  middleware: ['typescript']
})
class Index extends Vue {}
export default Index;
</script>

By adding middleware in the class you are creating a data property, which is why it appears not to work.

All 6 comments

I think this is what you want:

<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator';

import Logo from '~/components/Logo.vue';

@Component({
  components: {
    Logo
  },
  middleware: ['typescript']
})
class Index extends Vue {}
export default Index;
</script>

By adding middleware in the class you are creating a data property, which is why it appears not to work.

Thanks for the tip @danielroe, your solution is working!

Docs upgrade should be warranted regarding this...

@envision Feel free to send in a PR!

@manniL, I could make a PR but in this case I do not understand why the middleware property needs to be defined in the Component decorator, and why is it not working when defined in the actual component class?

cc @kevinmarrec

@envision declaring it in Component is IMO more logical if you take some of these following considerations :

Only nuxt-property-decorator allows to define it in classes (it uses something called Vue Component Hook registration) but I'm not a fan of this apparoach as it can brings undesirable issues like your case where middleware is handled by TypeScript as a data property and not as a Component option.

middleware, asyncData and all others Page API methods that integrates Nuxt are Component options, and that's why it should IMO stays in Component section as standard way, but you can use nuxt-property-decorator if you like the way to define things in the class. But IMO it's easier to read code when keeping Nuxt logic in Component section and your own logic in the class.

Nuxt TypeScript documentation is using vue-property-decorator and is declaring asyncData in Component options so docs don't need upgrade for now.

If stick with nuxt-property-decorator and have issues, please open a new issue on the respective repository :)

/cc @husayt

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vadimsg picture vadimsg  路  3Comments

gary149 picture gary149  路  3Comments

maicong picture maicong  路  3Comments

surmon-china picture surmon-china  路  3Comments

mikekidder picture mikekidder  路  3Comments