I am working on an ASP.NET project that uses Vue.js and jQuery. I have a JavaScript file (fields.js) that defines several classes (e.g., Users, Fields) and initializes a Vue instance. When I use the unminified version of the file, everything works as expected. However, when I use the minified version, I encounter runtime errors, such as:
TypeError: users.hasAllUsersSelected is not a function
I've confirmed that hasAllUsersSelected exists in the Users class and that the minified file is sent and received correctly (I can see the minified code in the browser's response tab).
This is a stripped down version of my set up:
fields.js
class Users {
constructor(users = [], ebus) {
this.users = users;
this.filteredUsers = users;
this.isDescSort = true;
this.$ebus = ebus;
}
hasAllUsersSelected() {
if (this.filteredUsers.length === 0) {
return false;
}
return this.filteredUsers.every(user => user.isSelected);
}
}
new Vue({
data() {
return {
users: new Users([], new Vue()),
};
},
methods: {
getUserList () {
let vals = [...document.querySelectorAll('#listEnrolledUsers > option')];
let userList = vals.map(user => new User(user.textContent.trim(), user.value, false));
userList = userList.filter((user, index) => index !== 0);
this.users = new Users(userList, this.$ebus);
},
mounted() {
this.getUserList();
console.log('Vue instance mounted');
console.log('users.hasAllUsersSelected:', typeof this.users.hasAllUsersSelected);
},
}).$mount('#app');
This file then gets minified by webpack (version ^5.99.9)
webpack.config.js
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
const outputFilename = '[name].[contenthash].js'
module.exports = (env = {}) => {
const bundleDefinitions = [
{
name: 'fields',
entry: { app:path.resolve(__dirname, '../path/to/fields/main/fields.js')},
outputPath: path.resolve(__dirname, '../path/to/fields/bundle'),
outputFilename: outputFilename,
needSourceMap: true,
},
];
const wanted = env.bundles
? env.bundles.split(',').map(s => s.trim())
: bundleDefinitions.map(b => b.name);
const configs = bundleDefinitions
.filter(b => wanted.includes(b.name))
.map(b => ({
name: b.name,
mode: 'production',
entry: b.entry,
output: {
path: b.outputPath,
filename: outputFilename,
chunkFilename: outputFilename,
clean: true,
},
...(b.needSourceMap ? { devtool: 'source-map' } : {}),
cache: {
type: 'filesystem',
buildDependencies: { config: [__filename] },
},
optimization: {
runtimeChunk: { name: `manifest.${b.name}` },
splitChunks: {
minSize: 0,
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
filename: b.vendorChunkName,
chunks: 'all',
enforce: true,
},
},
},
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
compress: true,
mangle: false,
output: { comments: false },
},
extractComments: false,
}),
],
},
}));
return configs;
};
if I call fields.js directly in my .aspx page where I need that class ala:
<script type="text/javascript" src="/path/to/fields/main/fields.js"> </script>
<span class="c9-clickable" v-on:click="users.toggleAllSelection()"><i v-bind:class="[users.hasAllUsersSelected() ? 'far fa-check-square' : 'far fa-square']"></i>Users</span>
Everything is fine.
But when I try to link the, successfully minified and recieved version of fields.js I get the above error.
<script type="text/javascript" src="/path/to/fields/bundle/<%= ManifestFileName %>"> </script>
<script type="text/javascript"src="/path/to/fields/bundle/<%= AppFileName %>"> </script>
<span class="c9-clickable" v-on:click="users.toggleAllSelection()"><i v-bind:class="[users.hasAllUsersSelected() ? 'far fa-check-square' : 'far fa-square']"></i>Users</span>
(Don't worry about how I get the manifest/app filename, it works perfectly. Again, I see the correct file and content response in the dev tools)
For the record I do have some jquery in my aspx file that I did not include because it doesn't directly manipulate users.hasAllUsersSelected and, again, directly linking the unminified file works so I know it's not jquery and vue interferring with each other.
The minification works. The minified files are generated and received by the aspx file. I don't understand what's going on.
Can some sweet, kind soul help me figure out what i'm doing wrong here??