Roots Discourse

Adding Vue.js to Sage 9: Dependencies and Approach

This latest iteration is working for me as well. Thanks for the hard work.
For those who haven’t learned yet. Sitepoint’s “Jump Start Vue.js” book is a great place to start. Wasn’t overwhelming.

I am still having occasional trouble compiling .vue files after following these instructions.

For the most part it works but occasionally my code will not compile with either yarn build or yarn start, and there’s no indication of why.

For example, here is some .vue file code that does not compile or produce any error messages for me:

<div v-if="retrieving">
	<p>Retrieving...</p>
</div>

<div v-else>
	<p>Retrieved!.</p>
</div>

The usual error message I would receive from chrome developer tools would be something like:
Component template should contain exactly one root element
which I understand.

However with Sage and the Vue integration method outlined in this post I receive no indication or message explaining the error. The yarn build simply hangs forever.

I’m sure there are other occasions where similar errors are not indicated as I have had similar trouble before.

Any ideas?

Wish I could help Stuart, but I’m just getting started with the Roots stack, myself.

I’m also having a small issue. Until this point, everything has been compiling fine, until trying to get mixins working properly. When creating one and using it all within a single file component – no problem. Works great. But when importing a mixin from an external file, it breaks the component. The external JS is even in the same directory.

So the external file (slideBase.js) looks something like this:

export const slideBase = {
    // mixin here
};

I also tried:

export default {
  // mixin here
}

In the single file component:

import { slideBase } from './slideBase.js'
export default {
  name: 'slide-half-2',
  mixins: [slideBase],
  data() {
    ...

This should be correct, yes?

Anyone else running into mixin problems? Couldn’t find any info remotely related to this. On the discourse or otherwise.

Cheers,

@db12

I haven’t had much experience with vue mixins but is it possible to use require instead of import? Something similar to the way I am defining components below:

components: {
	'test-component-1': require('./TestComponent1.vue').default,
	'test-component-2': require('./TestComponent2.vue'').default,
},

So in your case it would be:

mixins: [require("./slideBase.js").default]

I don’t understand why the ‘.default’ part is needed for my components. Perhaps the webpack script can be updated to avoid this?

Didn’t end up solving the problem. However, I’m getting the same console error that one of my variables is undefined. If my logic is correct, that could mean that it is indeed importing when trying both import and require, and something else is going on. I’m on Vue forums to try to understand the big picture of loading order for a component – since I’m using a vuex store and such. Will bring up more here if I find webpack/vue-loader to be the issue.

@pascallaliberte

A different issue – I’m having trouble getting global sass variables with sass-loader to work properly. I combined the instructions here with your method of adding vue-style-loader for CSS. So the rule is placed above the other test: /\.scss$/ and looks like this:

      {
        test: /\.scss$/,
        exclude: config.paths.assets,
        use: [
          { loader: 'vue-style-loader' },
          { loader: 'css-loader' },
          { loader: 'sass-loader',
            options: {
              data: `@import "scripts/vue/Project/SCSS/test.scss";`
            },
          },
        ],
      },

When I load a variable into test.scss, I’m still getting a build error ‘undefined variable’ when trying to use it in the single file component:

<style lang="scss">
</style>

The test: /\.css$/ rule from the above instructions is still present.

Any ideas?
Thanks.

Yeah, the one problem that I think is remaining from this setup is that the scss extracted from .vue files ends up being parsed before the rest of the site’s scss. Because of that, your global sass variables aren’t available at the time the .vue styles are parsed.

I haven’t looked deeper into why this is happening this way. Maybe someone will fall on the solution.

Am getting an error when i try to do any scss styles in the vue component. If left blank, it works. But if i add for eg body {}, i get a Module build failed: TypeError: Cannot read property 'postcss' of null at Processor.normalize

I wonder if Sage 10’s use of Laravel Mix will make Vue integration a little easier…

These configuration changes work well for the most part but I think they may be causing conflicts and browsersync issues…

2 Likes

I’ve followed all of the instructions here to get Vue setup. I’m using the latest Sage 9 version with Tailwind.

My console produces the following error:

[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

In place of the component Vue renders:
<!--function (a, b, c, d) { return createElement(vm, a, b, c, d, true); }-->

This guide worked almost perfect for me.

However, I had error Parsing error: Unexpected token .. every second time when I ran yarn build (wierd).
Here is my code which caused the error:

  computed: {
    ...mapGetters({// <-- yarn build breaks here sometimes
      allDogPlaceCoordinates: 'allDogPlaceCoordinates',
    }),
  },

The good news Looks like this solution resolves this build error:
update value 'ecmaVersion': 2017
to value 'ecmaVersion': 2018
site/web/app/themes/theme-name/.eslintrc.js

source:

This was very helpful, I managed to get it working with vuex,
Thank you for posting this. I was wondering if you were using the chrome vue extension with this and if you were is there something I need to enable to use it?

Never mind I got it working :slight_smile:

I had this issue and it ended up being because I completely skipped the bit where it says to resolve in the webpack.config.js file:

alias: {
      'vue$': 'vue/dist/vue.esm.js'

No idea why I did that and no doubt you’ve got it fixed after 5 months but as it came up as the first hit on Google for me, I thought I’d post.

Hi,

First of all, thank you for this solution!
Everything works very well, except async and await.

When I use them, I always get a “Unexpected token” compilation error.

I put the line ‘ecmaVersion’: 2018,

Do you have an idea?

Thank you !

Is there any follow up to this?

Thanks for the instructions - I’ve managed to get Vue working quite well. However, the one issue I’ve come across so far is that my Sage site doesn’t seem to want to change es6.

This is my .eslintrc.js file. It has ecmaVersion set to 2017, which is the version in which async await were added.

module.exports = {
  'root': true,
  'extends': [
    'eslint:recommended',
    'plugin:vue/essential',
  ],
  'globals': {
    'wp': true,
  },
  'env': {
    'node': true,
    'es6': true,
    'amd': true,
    'browser': true,
    'jquery': true,
  },
  'parserOptions': {
    'ecmaFeatures': {
      'globalReturn': true,
      'generators': false,
      'objectLiteralDuplicateProperties': false,
      'experimentalObjectRestSpread': true,
    },
    'ecmaVersion': 2017,
    'sourceType': 'module',
  },
  'plugins': [
    'import',
  ],
  'settings': {
    'import/core-modules': [],
    'import/ignore': [
      'node_modules',
      '\\.(coffee|scss|css|less|hbs|svg|json)$',
    ],
  },
  'rules': {
    'no-console': 0,
    'quotes': ['error', 'single'],
    'comma-dangle': [
      'error',
      {
        'arrays': 'always-multiline',
        'objects': 'always-multiline',
        'imports': 'always-multiline',
        'exports': 'always-multiline',
        'functions': 'ignore',
      },
    ],
  },
};

I’m still getting the following error within a Vue component that is using async await.

 ERROR  Failed to compile with 1 errors                                          9:12:30 PM

 error  in ./resources/assets/scripts/vue/RequestForQuote.vue?vue&type=script&lang=js&

Module build failed: 
47 :   methods: {
48 : 
49 :     /* eslint-disable no-unused-vars */
50 :   
51 :     async addProduct() {
               ^
Unexpected token (51:10)

 @ ./resources/assets/scripts/vue/RequestForQuote.vue?vue&type=script&lang=js& 1:0-289 1:310-596
 @ ./resources/assets/scripts/vue/RequestForQuote.vue
 @ ./resources/assets/scripts/routes/common.js
 @ ./resources/assets/scripts/main.js
 @ multi ./resources/assets/build/util/../helpers/hmr-client.js ./scripts/main.js ./styles/main.scss

Everyone has mentioned the 'ecmaVersion': 2018 fix, however that doesn’t work for me. I get the same error, and the impression that it’s not really changing anything, and Sage isn’t actually changing its ecma version.

When I’ve looked into the environments being used by eslint, it only seems to list es6 as an environment - changing this to something like es8 results in an error.

Would greatly appreciate any help on the matter - at the very least being shown how to definitively change the ecmaVersion within Sage.

Thanks!

1 Like

Facing the exact same problem.

I’m fairly certain the issue you’re encountering is not related to eslint–if it were a linting issue, the error should be something more like "I’m afraid you can’t use async" instead of Unexpected token which almost always means that a parser has encountered an unsupported language feature. As mentioned elsewhere, Sage 9 uses Buble instead of Bable to transpile JS, and so far as I can tell Buble does no support async–hence the error you’re seeing. I haven’t tested this, but I think you should be able to rip out Buble and replace it with Babel and then just change the loader here: https://github.com/roots/sage/blob/f3e794a09374d2f110742d15b9b975490fcddbee/resources/assets/build/webpack.config.js#L58

1 Like

I fixed the async/await problem by installing ‘babel-loader’ and replacing ‘buble’ with ‘babel-loader’ in webpack.config.js (remove ‘buble’ options):

 {
    test: /\.js$/,
    exclude: [
      /node_modules(?![/|\\](bootstrap|foundation-sites))/,
    ],
    use: [
      {loader: 'cache'},
      {loader: 'babel-loader', options: {}},
    ],
  },

Not sure what other effects this has (apparently performance), but it seems to work fine for me…

2 Likes

Thank you for your response (and you too @alwaysblank) you are both correct - replacing buble with babel-loader did the trick! Very thankful!