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 >
{{ 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;
}
CodePudding user response:
<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.