1

Been chasing this one for a little while, and managed to narrow it down to my webpack config. I have to use webpack for various reasons, so not using it isn't an option.

Basically I have a 'Hello World' Vue project. When I serve this app through npx vue-cli-service serve it works perfectly, and I get no issues. For reference I have a component that looks like this:

<template>
    <header class="app-header">
        {{ items }}
        {{ msg }}

        <ul>
            <li v-for="item in items" :key="item.message">
                {{ item.message }}
            </li>
        </ul>
    </header>
</template>

<script>
export default {
    name: 'TheAppHeader',
    props: {
        msg: String
    },
    data() {
        return {
            items: [{ message: 'Foo' }, { message: 'Bar' }],
        }
    },
    created() {
      // eslint-disable-next-line no-console
      console.log('here');
      this.items.push({ message: 'FooBar' });
    }
}
</script>

that works perfectly when served this way - the template that uses it does so via <TheAppHeader msg="test"></TheAppHeader>. I see the msg come through, and I see the rendered this.items correctly (as well as the console.log coming through).

When I build the app via npx webpack build the app half works. I see the msg come through as before, but this.items does not render and the console.log does not come through. Neither data() nor created() are invoked. I cannot figure out what is wrong with my webpack config to create such an obscure issue? Is this common?

my vue.config.js looks like this

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack: {
    devtool: 'source-map',
  }
})

and my webpack.config.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader')
const webpack = require('webpack');
const ESLintPlugin = require('eslint-webpack-plugin');


module.exports  = (env, argv) => { 
    let config = {
        target: 'web',
        mode: 'development',
        module: {
            rules: [
                {
                    test: /\.(png|jpe?g|gif|svg)$/i,
                    type: 'asset/resource',
                    generator: {
                        filename: 'images/[hash][ext][query]'
                    }
                },
                {  
                    test: /\.(woff|woff2|eot|ttf|otf)$/,
                    type: 'asset/resource',
                    generator: {
                        filename: 'fonts/[hash][ext][query]'
                    }
                },
                {
                    test: /\.vue$/,
                    loader: 'vue-loader',
                    options: {
                        babelParserPlugins: [
                          'jsx',
                          'classProperties',
                          'decorators-legacy'
                        ]
                      }
                },
                // this will apply to both plain `.js` files
                // AND `<script>` blocks in `.vue` files
                {
                    test: /\.js$/,
                    loader: 'babel-loader'
                },
                // this will apply to both plain `.css` files
                // AND `<style>` blocks in `.vue` files
                {
                    test: /\.css$/,
                    use: [
                        'vue-style-loader',
                        'css-loader'
                    ]
                },
            ],
        },
        entry: {
            vue:     './src/main.js'
        },
        optimization: {
            minimize: true
        },
        output: {
            filename: '[name].bundle.js',
            path: path.resolve(__dirname, 'distribution'),
            clean:true,
            publicPath: '/app/',
        },
        plugins: [
            new HtmlWebpackPlugin({
                template: './public/index.html'
            }),
            new VueLoaderPlugin(),
            new webpack.DefinePlugin({
                // Drop Options API from bundle
                __VUE_OPTIONS_API__: false,
                // Enable devtools support
                __VUE_PROD_DEVTOOLS__ : true,
                'process.env': {
                    BASE_URL: '"/"'
                  }
            }),
            new ESLintPlugin(
                {
                
                  extensions: [
                    '.js',
                    '.jsx',
                    '.vue'
                  ],
                  cache: true,
                  failOnWarning: false,
                  failOnError: true,
                  formatter: 'stylish',
                }),
        ],
    }
    return config;
}
10
  • Just confirmed it's nothing to do with using serve vs build - just built via the vue cli and served it via the same method for my webpack builds and same result. Commented Nov 2, 2022 at 12:35
  • Webpack config is hacky, there are "node_modules/" entries that aren't there normally. It's unknown why they are there in the first place. There shouldn't be separate Vue CLI and Webpack configs, it's either one or another. Vue CLI is a wrapper around Webpack. You can't extend Webpack in Vue CLI config. I wouldn't expect it to work correctly in its current state Commented Nov 2, 2022 at 12:56
  • @EstusFlask I am not trying to use both Vue CLI and WebPack. There is only two configs for the purpose of this test, hence why its pasted onto the hello world vue project. My actual application that only uses webpack and only has a webpack.config.js (where all of this is taken from, minus the vue.config.js) exhibits the exact same problem, created() and data() are never invoked. They are both in one app to prove that there is a difference in the builds, even though the webpack build appears to work correctly. Commented Nov 2, 2022 at 12:59
  • 1
    There seem to be contradictions. "When I build the app via npx webpack build the app half works." Then "even though the webpack build appears to work correctly". You may have hard time reproducing raw Webpack config from vue inspect, and @vue/cli-service isn't supposed to be used outside Vue CLI. I'd suggest to build the config from scratch. That data isn't triggered basically means that the comp isn't rendered. If there are no errors in the console, most likely because .vue wasn't correctly imported and there's no comp to render, so the problem is related to vue-loader. Commented Nov 2, 2022 at 13:08
  • 1
    Luckily there's an eslint rule to force composition - I've set it up so the next unlucky soul in this project that attempts to copy & paste from an example that happens to use the options API will at least get an error Commented Nov 2, 2022 at 14:18

1 Answer 1

2

<Component>.data() and <Component>.created() are part of the Options API (as per vuejs.org/api). By adding

    new webpack.DefinePlugin({
        // Drop Options API from bundle
        __VUE_OPTIONS_API__: false,
    }),

I was specifically disabling those functions from being called.

I should follow the composition way of doing it with that flag set, as per this answer: Vue 3 Composition API data() function I need to stop using data() and use the setup() call instead.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.