rollup-plugin-vue icon indicating copy to clipboard operation
rollup-plugin-vue copied to clipboard

Needs an extra plugin for `.css/.scss/.sass` (with Vue.js 3 beta)

Open akauppi opened this issue 4 years ago • 21 comments

Version

6.0.0-beta.6

Reproduction link

https://stackoverflow.com/questions/62384191/rollup-vue-and-buble-unexpected-token-in-scss-file/62625441#62625441

Steps to reproduce

6.0.0-beta.6. (was unable to fill that into the "version" field)

As @P-Seebauer mentions here,

the css needs an extra rollup css plugin, this is awkward because the css-only plugin seems like the wrong choice at first (“i have scss”),

That ticket is closed, but this anomaly remains. Thus the creation of this ticket, to track it.

Setup

Vue.js 3 (beta), e.g. 3.0.0-beta.15 Rollup 2.16.1 rollup-plugin-vue 6.0.0-beta.6

Expectation:

It is easy to build a Vue.js 3 (beta) project, using Rollup.

Actual:

One gets the following error message, and it is not clear a) what causes it, b) how to get rid of it:

$ npx rollup -c
[!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
src/App.vue?vue&type=style&index=0&id=7ba5bd90&scoped=true&lang.css (2:0)

First aid

The way around this was suggested by @P-Seebauer's comment (above). I added rollup-plugin-scss to the mix, and it seems to please Rollup. The build proceeds. It handles both .scss and .css files.

However, since Vue.js is expected to handle these, asking application developers to add such a plugin seems unnecessary.

Real fix

I cannot say, whether this falls to Vue.js 3 beta or the rollup-plugin-vue (also beta) domain. I do hope it gets ironed out, before the both are out of their betas.

What is expected?

Things "just work", without needing to add rollup-plugin-scss, to handle Vue styles.

What is actually happening?

One needs to add that plugin.


I can be of assistance in testing.

akauppi avatar Jun 28 '20 17:06 akauppi

To reproduce:

$ git clone [email protected]:akauppi/GroundLevel-es6-firebase-web.git
$ cd GroundLevel*
  • Check the README for setting up the project
$ npm install
$ npm run build

That should pass. Now edit rollup.config.prod.js and switch off:

const scssHackNeeded = true;   // <-- make it false

Repeat.

$ npm run build
...
src/main.js → public/dist...
[!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
src/App.vue?vue&type=style&index=0&id=7ba5bd90&scoped=true&lang.css (2:0)
Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)

akauppi avatar Jul 07 '20 15:07 akauppi

Seems like vite can handle scss/sass correctly.

XiongAmao avatar Oct 06 '20 10:10 XiongAmao

Is there a workaround that allows one to process a Vue SFC just like before (i.e. prior to version 6 releases)? In my rollup.config.js, I have two build configurations:

  • using vuePlugin() without any options to keep the SFC’s style block contents as part of the generated JS bundle
  • using vuePlugin({ css: false }) and a custom rollup plugin to discard the style block contents entirely

Adding another plugin processor like the one from rollup-plugin-scss after the vuePlugin() step for scenario 1 doesn’t produce a desirable result as it generates a separate CSS file.

Also, the css option seems to be completely missing from rollup-plugin-vue now. Was it deprecated or replaced?

kleinfreund avatar Oct 25 '20 08:10 kleinfreund

Hi @kleinfreund .

We recently face the same issue trying to make our Vue 2 component library "Vue 3 compliant".

Your problem looks very similar to this one, so I will reproduce my answer here as this issue is used as a tracker.

Using rollup-plugin-vue v6.0.0 we were able to inject CSS in Javascript by adding the rollup-plugin-postcss plugin with the following config:

...
import vue from 'rollup-plugin-vue'; // v6.0.0
import postcss from 'rollup-plugin-postcss'; // v4.0.0

export default {
  input: ...,
  output: ...,
  plugin: [
    ...
    vue({
      preprocessStyles: true
    }),
    postcss()
  ]
}

Notes: the rollup-plugin-postcss needs postcss as a peer dependecy.

Hope this helps. :-)

NicolasRichel avatar Dec 18 '20 17:12 NicolasRichel

I'm running into the same issue. I'm trying to compile a component or plugin into a standalone piece that I can import without needing to go through a bundler. I'm attempting to make a way to load extensions into an electron app built with vue 3. I'm using an absolutely bare minimal component. It's just a template with a single paragraph tag and a style tag that sets the background of that paragraph tag. the vue plugin seems to (according to the docs) support parsing the style tag but when I try it, I get:

[!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)

and it points at the opening curly in the css.

Using the postcss plugin as mentioned above does seem to make it work though.

jdfwarrior avatar Jan 05 '21 16:01 jdfwarrior

I've been sorting out the [!] Error: Unexpected token problem for a day now. I think the root cause for this issue is described in #410 (despite its title still valid for 6.0.0).

mnlipp avatar Feb 28 '21 11:02 mnlipp

@NicolasRichel Unfortunately, this doesn't seem to work for scoped scss style blocks in SFC's. It requires rollup-plugin-scss, but that plugin generates a .css and all scoping gets lost..

DaanDL avatar Mar 29 '21 16:03 DaanDL

I struggle with the same problem. I tryed also the solution from NicolasRichel but no way. Its important to keep the css inside the component scoped. And an aditional main css file is needed which contains scss variables and functions they have to be used inside the vue components. But this file should get loaded only one time. i have really no idea how to start here.

SvenBudak avatar Apr 07 '21 06:04 SvenBudak

@SvenBudak I gave up, and ditched rollup for Vite 2 (which uses rollup with a specific set of plugins in the background). It all works now as intended without much config.

DaanDL avatar Apr 07 '21 12:04 DaanDL

@DaanDL But Vite 2 is so much more (and complex). I never figured out how to get it working. Do you have a simple configuration that only does what rollup-plugin-vue is supposed to do (in my case: create a browser-module with the Vue 3 components, triggered by some simple node.js script invocation).

mnlipp avatar Apr 07 '21 13:04 mnlipp

Dear god... Sience 2 weeks i try to generate a library for vue that is just working 😂 I have experiance with this in angular. but i cant find any helpfull for vue. Its a mess...

SvenBudak avatar Apr 07 '21 18:04 SvenBudak

@DaanDL But Vite 2 is so much more (and complex). I never figured out how to get it working. Do you have a simple configuration that only does what rollup-plugin-vue is supposed to do (in my case: create a browser-module with the Vue 3 components, triggered by some simple node.js script invocation).

I purely use Vite for library builds, since I'm building a component library. My vite.config looks like this:

`import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import path from 'path';

// https://vitejs.dev/config/ export default defineConfig({ plugins: [vue()], // Make sure we can do @/components/xxx style imports alias: [ { find: '@', replacement: path.resolve(__dirname, 'src') } ], // Enable library mode: only create ES builds build: { sourcemap: true, lib: { entry: path.resolve(__dirname, 'bundler/entry.js'), name: 'GalleryComponentLibrary', formats: ['es'] }, rollupOptions: { // make sure to externalize deps that shouldn't be bundled // into your library external: ['vue'], output: { // Provide global variables to use in the UMD build // for externalized deps globals: { vue: 'Vue' } } } } });`

DaanDL avatar Apr 08 '21 05:04 DaanDL

@DaanDL Thanks. Going to try this in one of my next projects. Currently (only using CSS, not SCSS or SASS) things work for me with "plain" rollup.

mnlipp avatar Apr 08 '21 08:04 mnlipp

Thanks @NicolasRichel , it worked perfectly for me!

Just complementing, for those who need to add something from SCSS in all components it looks like this:

...
import vue from 'rollup-plugin-vue'; // v6.0.0
import postcss from 'rollup-plugin-postcss'; // v4.0.0

export default {
  input: ...,
  output: ...,
  plugin: [
    ...
    vue({
      preprocessStyles: true,
      preprocessOptions: {
        scss: {
          additionalData: `@import 'src/styles/abstract/mixins';`,
        },
      }
    }),
    postcss()
  ]
}

plinionaves avatar Apr 14 '21 01:04 plinionaves

@plinionaves i have this config:

// rollup.config.js
import fs from 'fs';
import path from 'path';
import vue from 'rollup-plugin-vue';
import alias from '@rollup/plugin-alias';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
import replace from '@rollup/plugin-replace';
import babel from '@rollup/plugin-babel';
import {terser} from 'rollup-plugin-terser';
import postcss from 'rollup-plugin-postcss'; // v4.0.0
import minimist from 'minimist';

// Get browserslist config and remove ie from es build targets
const esbrowserslist = fs.readFileSync('./.browserslistrc')
    .toString()
    .split('\n')
    .filter((entry) => entry && entry.substring(0, 2) !== 'ie');

const argv = minimist(process.argv.slice(2));

const projectRoot = path.resolve(__dirname, '..');

const baseConfig = {
    input: 'src/entry.ts',
    plugins: {
        preVue: [
            alias({
                entries: [
                    {
                        find: '@',
                        replacement: `${path.resolve(projectRoot, 'src')}`,
                    },
                ],
            }),
        ],
        replace: {
            'process.env.NODE_ENV': JSON.stringify('production'),
        },
        vue: {
            // css: true,
            preprocessStyles: true,
            preprocessOptions: {
                scss: {
                    additionalData: `@import 'src/styles';`,
                },
            },
            template: {
                isProduction: true,
            },
        },
        postcss,
        postVue: [
            resolve({
                extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue'],
            }),
        ],
        babel: {
            exclude: 'node_modules/**',
            extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue'],
            babelHelpers: 'bundled',
        },
    },
};

// ESM/UMD/IIFE shared settings: externals
// Refer to https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency
const external = [
    // list external dependencies, exactly the way it is written in the import statement.
    // eg. 'jquery'
    'vue',
];

// UMD/IIFE shared settings: output.globals
// Refer to https://rollupjs.org/guide/en#output-globals for details
const globals = {
    // Provide global variable names to replace your external imports
    // eg. jquery: '$'
    vue: 'Vue',
};

// Customize configs for individual targets
const buildFormats = [];
if (!argv.format || argv.format === 'es') {
    const esConfig = {
        ...baseConfig,
        input: 'src/entry.esm.ts',
        external,
        output: {
            file: 'dist/mrm-vue-ui.esm.js',
            format: 'esm',
            exports: 'named',
        },
        plugins: [
            replace(baseConfig.plugins.replace),
            ...baseConfig.plugins.preVue,
            vue(baseConfig.plugins.vue),
            ...baseConfig.plugins.postVue,
            babel({
                ...baseConfig.plugins.babel,
                presets: [
                    [
                        '@babel/preset-env',
                        {
                            targets: esbrowserslist,
                        },
                    ],
                ],
            }),
            commonjs(),
        ],
    };
    buildFormats.push(esConfig);
}

if (!argv.format || argv.format === 'cjs') {
    const umdConfig = {
        ...baseConfig,
        external,
        output: {
            compact: true,
            file: 'dist/mrm-vue-ui.ssr.js',
            format: 'cjs',
            name: 'MrmVueUi',
            exports: 'auto',
            globals,
        },
        plugins: [
            replace(baseConfig.plugins.replace),
            ...baseConfig.plugins.preVue,
            vue({
                ...baseConfig.plugins.vue,
                template: {
                    ...baseConfig.plugins.vue.template,
                    optimizeSSR: true,
                },
            }),
            ...baseConfig.plugins.postVue,
            babel(baseConfig.plugins.babel),
            commonjs(),
        ],
    };
    buildFormats.push(umdConfig);
}

if (!argv.format || argv.format === 'iife') {
    const unpkgConfig = {
        ...baseConfig,
        external,
        output: {
            compact: true,
            file: 'dist/mrm-vue-ui.min.js',
            format: 'iife',
            name: 'MrmVueUi',
            exports: 'auto',
            globals,
        },
        plugins: [
            replace(baseConfig.plugins.replace),
            ...baseConfig.plugins.preVue,
            vue(baseConfig.plugins.vue),
            ...baseConfig.plugins.postVue,
            babel(baseConfig.plugins.babel),
            commonjs(),
            terser({
                output: {
                    ecma: 5,
                },
            }),
        ],
    };
    buildFormats.push(unpkgConfig);
}

// Export config
export default buildFormats;

And i get this error:

 error  in ./src/lib-components/content-wrapper.vue?vue&type=style&index=0&id=41cf14b2&scoped=true&lang=scss&

Syntax Error: TypeError: this.getOptions is not a function


 @ ./node_modules/vue-style-loader??ref--8-oneOf-1-0!./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/c
js.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/lib-components/content-wrapper.vue?vue&type=style&index=0&id=41cf14b2&scoped=true&lang=scss& 4:14-470 15:3-20:5 16:22-478
 @ ./src/lib-components/content-wrapper.vue?vue&type=style&index=0&id=41cf14b2&scoped=true&lang=scss&
 @ ./src/lib-components/content-wrapper.vue
 @ ./src/lib-components/index.ts
 @ ./src/entry.esm.ts
 @ ./dev/serve.ts
 @ multi (webpack)-dev-server/client?http://192.168.188.61:8080&sockPath=/sockjs-node (webpack)/hot/dev-server.js ./dev/serve.ts

He dont like the scss in: <style scoped lang="scss"> how did you solved this?

SvenBudak avatar Apr 14 '21 06:04 SvenBudak

Hi @SvenBudak

I noticed that in your baseConfig it was missing to call postcss as a function:

         vue: {
            // css: true,
            preprocessStyles: true,
            preprocessOptions: {
                scss: {
                    additionalData: `@import 'src/styles';`,
                },
            },
            template: {
                isProduction: true,
            },
        },
        postcss(), // <-- here
        postVue: [
            resolve({
                extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue'],
            }),
        ],

If you need it too, here's the complete config that worked for me: rollup.cofig.js

plinionaves avatar Apr 14 '21 11:04 plinionaves

Thanks @plinionaves

But unfortunately it still doesn't work even with your config. I still get the same error:

error in ./src/lib-components/content-wrapper.vue?vue&type=style&index=0&id=41cf14b2&scoped=true&lang=scss&

It is a very simple component:

<template>
  <section :id="addId" :class="[addClass, gradient, theme]" :style="{backgroundColor: backgroundColor}">
    <div class="inner" :style="{maxWidth: maxWidth + 'px', 'padding': disablePadding ? '0' : null}">
      <slot></slot>
    </div>
  </section>
</template>

<script lang="ts">
import Vue from "vue";

export default /*#__PURE__*/Vue.extend({
  name: 'ContentWrapper',
  props: {
    addId: {
      type: String
    },
    addClass: {
      type: String
    },
    theme: {
      type: String
    },
    backgroundColor: {
      type: String
    },
    gradient: {
      type: String
    },
    maxWidth: {
      type: Number
    },
    disablePadding: {
      type: Boolean,
      default: false
    }
  }
});
</script>

<style scoped lang="scss">

.light {
  color: blue;
}

.dark {
  color: red;
}

</style>

SvenBudak avatar Apr 14 '21 13:04 SvenBudak

Thanks @plinionaves

But unfortunately it still doesn't work even with your config. I still get the same error:

error in ./src/lib-components/content-wrapper.vue?vue&type=style&index=0&id=41cf14b2&scoped=true&lang=scss&

It is a very simple component:

<template>
  <section :id="addId" :class="[addClass, gradient, theme]" :style="{backgroundColor: backgroundColor}">
    <div class="inner" :style="{maxWidth: maxWidth + 'px', 'padding': disablePadding ? '0' : null}">
      <slot></slot>
    </div>
  </section>
</template>

<script lang="ts">
import Vue from "vue";

export default /*#__PURE__*/Vue.extend({
  name: 'ContentWrapper',
  props: {
    addId: {
      type: String
    },
    addClass: {
      type: String
    },
    theme: {
      type: String
    },
    backgroundColor: {
      type: String
    },
    gradient: {
      type: String
    },
    maxWidth: {
      type: Number
    },
    disablePadding: {
      type: Boolean,
      default: false
    }
  }
});
</script>

<style scoped lang="scss">

.light {
  color: blue;
}

.dark {
  color: red;
}

</style>

Did you solve it in the back? I also meet this problem, do not know how to solve it

973782523 avatar Jun 08 '21 04:06 973782523

No i was not able to solve it... But i asked in the vue Issue Board for a documentation for this: https://github.com/vuejs/docs-next/issues/1060

SvenBudak avatar Jun 08 '21 07:06 SvenBudak

No i was not able to solve it... But i asked in the vue Issue Board for a documentation for this: vuejs/docs-next#1060

rollup-plugin-styles Is the JS import form can be solved, I solved

973782523 avatar Jun 08 '21 15:06 973782523

here is my config

    plugins: [
      vue(),
      postcss({
        extract: true,
      }),
    ],

bowencool avatar Jul 07 '21 05:07 bowencool