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

At least one <template> or <script> is required in a single file component #527

Closed
6 tasks done
Javid-Izadfar opened this issue May 6, 2023 · 15 comments · Fixed by #575
Closed
6 tasks done

At least one <template> or <script> is required in a single file component #527

Javid-Izadfar opened this issue May 6, 2023 · 15 comments · Fixed by #575
Labels
to triage This issue needs to be triaged

Comments

@Javid-Izadfar
Copy link

Describe the bug

I'm receiving At least one <template> or <script> is required in a single file component for every .story.vue file I've got on a Nuxt3 (@3.3.2 and @3.4.3) project.

Reproduction

https://stackblitz.com/edit/histoire-vue3-starter-wlv4el?file=package.json

System Info

System:
    OS: Linux 5.10 Ubuntu 20.04 LTS (Focal Fossa)
    CPU: (12) x64 Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
    Memory: 3.70 GB / 7.72 GB
    Container: Yes
    Shell: 5.0.16 - /bin/bash
  Binaries:
    Node: 18.15.0 - ~/.nvm/versions/node/v18.15.0/bin/node
    npm: 9.6.3 - ~/.nvm/versions/node/v18.15.0/bin/npm
  npmPackages:
    @histoire/plugin-nuxt: 0.16.1 => 0.16.1 
    @histoire/plugin-vue: 0.16.1 => 0.16.1 
    histoire: 0.16.1 => 0.16.1

Used Package Manager

npm

Validations

@Javid-Izadfar Javid-Izadfar added the to triage This issue needs to be triaged label May 6, 2023
@stackblitz
Copy link

stackblitz bot commented May 6, 2023

Fix this issue in StackBlitz Codeflow Start a new pull request in StackBlitz Codeflow.

@danlourenco
Copy link

Getting the same thing.

@samplep182
Copy link

Facing same issue on MacOS using pnpm.

@romainl
Copy link

romainl commented May 26, 2023

FWIW, removing any reference to @histoire/plugin-nuxt from histoire.config.ts made the error disappear:

import { defineConfig } from "histoire";
import { HstVue } from "@histoire/plugin-vue";
// import { HstNuxt } from "@histoire/plugin-nuxt";

export default defineConfig({
  plugins: [
    HstVue(),
    // HstNuxt()
  ],
});

which is rather surprising since the stack trace doesn't mention plugin-nuxt at all:

Error while collecting story /Users/username/project/components/Meow.story.vue:
SyntaxError: At least one <template> or <script> is required in a single file component.
    at Object.parse$4 [as parse] (/Users/username/project/node_modules/@vue/compiler-sfc/dist/compiler-sfc.cjs.js:5269:21)
    at createDescriptor (/Users/username/project/node_modules/@vitejs/plugin-vue/dist/index.cjs:74:43)
    at transformMain (/Users/username/project/node_modules/@vitejs/plugin-vue/dist/index.cjs:2277:34)
    at TransformContext.transform (/Users/username/project/node_modules/@vitejs/plugin-vue/dist/index.cjs:2798:16)
    at Object.transform (file:///Users/username/project/node_modules/vite/dist/node/chunks/dep-934dbc7c.js:42883:44)
    at async loadAndTransform (file:///Users/username/project/node_modules/vite/dist/node/chunks/dep-934dbc7c.js:53349:29)

…and doesn't really help, since we are using Histoire in a Nuxt 3 project (autoloading and all).

If it helps, I logged descriptor ONCE to the console in /Users/username/project/node_modules/@vue/compiler-sfc/dist/compiler-sfc.cjs.js (which, I am aware is not part of this project):

console.log('descriptor', descriptor); // eslint-disable-line
if (!descriptor.template && !descriptor.script && !descriptor.scriptSetup) {
    errors.push(new SyntaxError(`At least one <template> or <script> is required in a single file component.`));
}

The output is below:

descriptor {
  filename: '/Users/username/project/components/Meow.story.vue',
  source: '<script>\n' +
    'console.log("Meow");\n' +
    '</script>\n' +
    '<template>\n' +
    '  <Story title="Meow">\n' +
    '    <Variant title="One Meow"> 🐱 </Variant>\n' +
    '    <Variant title="Two Meows"> 🐱🐱 </Variant>\n' +
    '    <Variant title="Three Meows"> 🐱🐱🐱 </Variant>\n' +
    '  </Story>\n' +
    '</template>\n',
  template: {
    type: 'template',
    content: '\n' +
      '  <Story title="Meow">\n' +
      '    <Variant title="One Meow"> 🐱 </Variant>\n' +
      '    <Variant title="Two Meows"> 🐱🐱 </Variant>\n' +
      '    <Variant title="Three Meows"> 🐱🐱🐱 </Variant>\n' +
      '  </Story>\n',
    loc: {
      source: '\n' +
        '  <Story title="Meow">\n' +
        '    <Variant title="One Meow"> 🐱 </Variant>\n' +
        '    <Variant title="Two Meows"> 🐱🐱 </Variant>\n' +
        '    <Variant title="Three Meows"> 🐱🐱🐱 </Variant>\n' +
        '  </Story>\n',
      start: [Object],
      end: [Object]
    },
    attrs: {},
    ast: {
      type: 1,
      ns: 0,
      tag: 'template',
      tagType: 0,
      props: [],
      isSelfClosing: false,
      children: [Array],
      loc: [Object],
      codegenNode: undefined
    }
  },
  script: {
    type: 'script',
    content: '\nconsole.log("Meow");\n',
    loc: {
      source: '\nconsole.log("Meow");\n',
      start: [Object],
      end: [Object]
    },
    attrs: {}
  },
  scriptSetup: null,
  styles: [],
  customBlocks: [],
  cssVars: [],
  slotted: false,
  shouldForceReload: [Function: shouldForceReload]
}
descriptor {
  filename: '/Users/username/project/components/Meow.story.vue',
  source: '\n' +
    'console.log("Meow");\n' +
    '\n' +
    'const _sfc_main = {}\n' +
    'import { createTextVNode as _createTextVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock } from "vue"\n' +
    '\n' +
    'function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {\n' +
    '  const _component_Variant = _resolveComponent("Variant")\n' +
    '  const _component_Story = _resolveComponent("Story")\n' +
    '\n' +
    '  return (_openBlock(), _createBlock(_component_Story, { title: "Meow" }, {\n' +
    '    default: _withCtx(() => [\n' +
    '      _createVNode(_component_Variant, { title: "One Meow" }, {\n' +
    '        default: _withCtx(() => [\n' +
    '          _createTextVNode(" 🐱 ")\n' +
    '        ]),\n' +
    '        _: 1 /* STABLE */\n' +
    '      }),\n' +
    '      _createVNode(_component_Variant, { title: "Two Meows" }, {\n' +
    '        default: _withCtx(() => [\n' +
    '          _createTextVNode(" 🐱🐱 ")\n' +
    '        ]),\n' +
    '        _: 1 /* STABLE */\n' +
    '      }),\n' +
    '      _createVNode(_component_Variant, { title: "Three Meows" }, {\n' +
    '        default: _withCtx(() => [\n' +
    '          _createTextVNode(" 🐱🐱🐱 ")\n' +
    '        ]),\n' +
    '        _: 1 /* STABLE */\n' +
    '      })\n' +
    '    ]),\n' +
    '    _: 1 /* STABLE */\n' +
    '  }))\n' +
    '}\n' +
    '\n' +
    '\n' +
    "import _export_sfc from '\x00plugin-vue:export-helper'\n" +
    `export default /*#__PURE__*/_export_sfc(_sfc_main, [['render',_sfc_render],['__file',"/Users/username/project/components/Meow.story.vue"]])`,
  template: null,
  script: null,
  scriptSetup: null,
  styles: [],
  customBlocks: [],
  cssVars: [],
  slotted: false,
  shouldForceReload: [Function: shouldForceReload]
}

Observations:

  • descriptor is logged twice
  • it seems OK the first time, with template and script members that look like what I have in my file
  • which shouldn't trigger the error
  • but, the second time, the source is not the actual content of the file but the JavaScript that would result from its compilation, which can't be parsed like a regular SFC
  • so there is no template or script anymore
  • which triggers the error

Hypothesis:

A first pass is made by either plugin-vue or plugin-nuxt, with the actual content of the file, which seems to "work", but there is a second pass that uses a JavaScript representation of the content of the file, which doesn't work.
The fact that there are two passes is IMO the root cause of all this.


No Storybook, no Histoire… The "stories" situation is not very good at the moment for Nuxt 3 users.

@DanielleConstell
Copy link

DanielleConstell commented May 26, 2023

Also having this issue with a complete clean nuxt install and these packages;
"@histoire/plugin-nuxt": "^0.16.1",
"@histoire/plugin-vue": "^0.16.1",
"histoire": "^0.16.1",
"nuxt": "^3.5.1",

Removing any reference to @histoire/plugin-nuxt from histoire.config.ts caused other errors

@awacode21
Copy link

i am currently migrating my vue project to a nuxt project. But i also get this issue with histoire which makes it impossible to use histoire with nuxt3. Any idea or workaround?

@romainl
Copy link

romainl commented Jun 7, 2023

@awacode21 our current workaround is to keep Nuxt out of our components as much as possible. It sort of gives us the benefits of agnosticism (for some meaning of agnosticism), but Nuxt's auto-imports and all are hard to let go :-(.

@ramonakira
Copy link

I am also experiencing this issue.

2 similar comments
@t0byman
Copy link

t0byman commented Jun 8, 2023

I am also experiencing this issue.

@fingm-t
Copy link

fingm-t commented Jun 15, 2023

I am also experiencing this issue.

@romainl
Copy link

romainl commented Jun 22, 2023

Upgrading "@histoire/plugin-nuxt" to 0.16.2 somewhat made the error and stack trace go away, but there is still no Nuxt autoloading or other Nuxt-provided features.

@ianjamieson
Copy link

I am getting this error when using histoire with a nuxt module that I am creating.

In my module configuration I have this to import the components:

  hooks: {
    'components:dirs'(dirs) {
      dirs.push({
        path: fileURLToPath(new URL('./runtime/components', import.meta.url)),
        prefix: 'Tx',
      });
    },
    'imports:dirs'(dirs) {
      dirs.push(fileURLToPath(new URL('./runtime/composables', import.meta.url)));
      dirs.push(fileURLToPath(new URL('./runtime/enums', import.meta.url)));
    },
  },

Which works ok, but when I add the global: true option (so I can auto import components with the :is directive), like this:

  hooks: {
    'components:dirs'(dirs) {
      dirs.push({
        path: fileURLToPath(new URL('./runtime/components', import.meta.url)),
        prefix: 'Tx',
       global: true
      });
    }
  },

This is when I get the error mentioned above.

@nashtonentwined
Copy link

nashtonentwined commented Jul 25, 2023

I managed to get passed this issue by editing @historie/plugin-nuxt/dist/index.js and resolving with the vuePlugins but not updating the config object.

nuxt.hook('vite:extendConfig', (config, { isClient }) => {
                    // @ts-ignore
                    if (isClient) {
                      const plugins = []  // <-----------
                        for (const name in vuePlugins) {
                            if (!config.plugins?.some(p => p?.name === name)) {
                                const [plugin, key] = vuePlugins[name];
                                // @ts-ignore
                                // config.plugins.push(plugin(config[key]));
                                plugins.push(plugin(config[key]));  // <-----------
                            }
                        }

                        resolve({
                          ...config,
                          plugins: [  // <-----------
                            ...config.plugins,  // <-----------
                            ...plugins,  // <-----------
                          ],  // <-----------
                        });
                    }
                });

This stopped the files from compiling twice, although i still have the same issue when using for example nuxt-icon package.

@cutugno01
Copy link

I managed to get passed this issue by editing @historie/plugin-nuxt/dist/index.js and resolving with the vuePlugins but not updating the config object.

nuxt.hook('vite:extendConfig', (config, { isClient }) => {
                    // @ts-ignore
                    if (isClient) {
                      const plugins = []  // <-----------
                        for (const name in vuePlugins) {
                            if (!config.plugins?.some(p => p?.name === name)) {
                                const [plugin, key] = vuePlugins[name];
                                // @ts-ignore
                                // config.plugins.push(plugin(config[key]));
                                plugins.push(plugin(config[key]));  // <-----------
                            }
                        }

                        resolve({
                          ...config,
                          plugins: [  // <-----------
                            ...config.plugins,  // <-----------
                            ...plugins,  // <-----------
                          ],  // <-----------
                        });
                    }
                });

This stopped the files from compiling twice, although i still have the same issue when using for example nuxt-icon package.

This seems to be working for me.
It is also solving an error in @nuxt/devtools/dist/runitme/plugins/view/Main.vue indicating to import type { CSSProperties } from 'vue'

Akryum added a commit that referenced this issue Aug 13, 2023
Co-authored-by: Guillaume Chau <guillaume.b.chau@gmail.com>
@samuveth
Copy link

I'm still getting this error for 'nuxt-icon' and 'nuxt-icons' plugins.

[vite:vue] At least one <template> or <script> is required in a single file component.
file: /Users/sam/dev/clones/nuxt-tune/node_modules/nuxt-icon/dist/runtime/Icon.vue?nuxt_component=async
node:internal/process/promises:279
            triggerUncaughtException(err, true /* fromPromise */);
            ^

SyntaxError: At least one <template> or <script> is required in a single file component.
    at Object.parse$2 [as parse] (/Users/sam/dev/clones/nuxt-tune/node_modules/@vue/compiler-sfc/dist/compiler-sfc.cjs.js:1275:7)
    at createDescriptor (/Users/sam/dev/clones/nuxt-tune/node_modules/@vitejs/plugin-vue/dist/index.cjs:84:43)
    at transformMain (/Users/sam/dev/clones/nuxt-tune/node_modules/@vitejs/plugin-vue/dist/index.cjs:2282:34)
    at Object.transform (/Users/sam/dev/clones/nuxt-tune/node_modules/@vitejs/plugin-vue/dist/index.cjs:2814:16)
    at /Users/sam/dev/clones/nuxt-tune/node_modules/vite-plugin-inspect/dist/index.cjs:932:28
    at Object.plugin2.<computed> (/Users/sam/dev/clones/nuxt-tune/node_modules/vite-plugin-inspect/dist/index.cjs:919:16)
    at file:///Users/sam/dev/clones/nuxt-tune/node_modules/rollup/dist/es/shared/node-entry.js:25518:40 {
  id: '/Users/sam/dev/clones/nuxt-tune/node_modules/nuxt-icon/dist/runtime/Icon.vue?nuxt_component=async',
  plugin: 'vite:vue',
  name: 'RollupError',
  hook: 'transform',
  code: 'PLUGIN_ERROR',
  watchFiles: [
    '/Users/sam/dev/clones/nuxt-tune/node_modules/@histoire/app/dist/bundle-main.js',
    '/Users/sam/dev/clones/nuxt-tune/node_modules/@histoire/app/dist/bundle-sandbox.js',
    '/Users/sam/dev/clones/nuxt-tune/node_modules/@histoire/app/dist/bundled/sandbox.js',
    '/Users/sam/dev/clones/nuxt-tune/node_modules/@histoire/app/dist/app/style/sandbox.css',
    '/Users/sam/dev/clones/nuxt-tune/node_modules/@histoire/app/dist/bundled/index.js',
    '/Users/sam/dev/clones/nuxt-tune/node_modules/@histoire/app/dist/style.css',
    '/Users/sam/dev/clones/nuxt-tune/node_modules/@histoire/app/dist/bundled/style.css',
    
    ```

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
to triage This issue needs to be triaged
Projects
None yet
Development

Successfully merging a pull request may close this issue.