vuejs / rollup-plugin-vue

Roll .vue files
https://vuejs.github.io/rollup-plugin-vue
MIT License
843 stars 147 forks source link

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

Open akauppi opened 4 years ago

akauppi commented 4 years ago

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 commented 4 years ago

To reproduce:

$ git clone git@github.com:akauppi/GroundLevel-es6-firebase-web.git
$ cd GroundLevel*
$ 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)
XiongAmao commented 3 years ago

Seems like vite can handle scss/sass correctly.

kleinfreund commented 3 years ago

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:

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?

NicolasRichel commented 3 years ago

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. :-)

jdfwarrior commented 3 years ago

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.

mnlipp commented 3 years ago

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).

DaanDL commented 3 years ago

@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..

SvenBudak commented 3 years ago

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.

DaanDL commented 3 years ago

@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.

mnlipp commented 3 years ago

@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).

SvenBudak commented 3 years ago

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...

DaanDL commented 3 years ago

@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' } } } } });`

mnlipp commented 3 years ago

@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.

plinionaves commented 3 years ago

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()
  ]
}
SvenBudak commented 3 years ago

@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?

plinionaves commented 3 years ago

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

SvenBudak commented 3 years ago

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>
973782523 commented 3 years ago

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

SvenBudak commented 3 years ago

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

973782523 commented 3 years ago

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

bowencool commented 3 years ago

here is my config

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