Search code examples
typescriptvuejs3webpack-4

Vue3 without using the cli service


I am trying to build a vue 3 project without the cli service (which is just a webpack wrapper)

package.json

{
  "name": "test",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "test": "webpack"
  },
  "dependencies": {
    "axios": "^0.24.0",
    "core-js": "^3.6.5",
    "vue": "^3.2.21",
    "vue-loader": "^15.9.8",
    "vue-router": "^4.0.0-0",
    "vue-style-loader": "^4.1.2",
    "vuex": "^4.0.2"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^4.18.0",
    "@typescript-eslint/parser": "^4.18.0",
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-typescript": "^4.5.15",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0",
    "@vue/eslint-config-typescript": "^7.0.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^7.0.0",
    "typescript": "~4.1.5",
    "webpack": "^4.0.0",
    "node-sass": "^6.0.1",
    "sass-loader": "^10"
  }
}

webpack.config.js

const path = require('path');
const { VueLoaderPlugin } = require('vue-loader');
// const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
    mode: 'development',
    entry: {
        project1: `./src/project1/main.ts`
    },
    output: {
        path: path.resolve(__dirname, './dist'),
        publicPath: '/wwwroot/vue/dist/',
        filename: '[name].js'
    },
    resolve: {
        extensions: ['.tsx','.ts','.mjs','.js','.jsx','.vue','.json','.wasm','.scss','.svg'],
        alias: {
            vue$: 'vue/dist/vue.runtime.esm-bundler.js',
            '@': path.join(__dirname, './src/')
        }
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader',
            },
            {
                test: /\.ts$/,
                loader: 'ts-loader',
                options: {
                    appendTsSuffixTo: [/\.vue$/]
                }
            },
            {
                test: /\.js$/,
                loader: "babel-loader",
                exclude: /node_modules/
            },
            {
                test: /\.s(c|a)ss$/,
                use: ['vue-style-loader', 'css-loader']
            },
            {
                test: /.css$/,
                use: ['vue-style-loader', 'css-loader',]
            }
        ]
    },
    plugins: [
        new VueLoaderPlugin()
    ]
}

main.ts

import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

App.vue

<template>
  <div>test</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
    name: 'App'
})
</script>

I tried everything I could find online but it keeps giving me the same error (on devtools)

Cannot read properties of undefined (reading '_c')
at Proxy.render
at renderComponentRoot
at ReactiveEffect.run
...

The reason I want to do it this way (and not using the CLI service) is because I need to build multiple small projects and not just one. Also, I don't need all the dist/public folder stuff it generates, I just need to generate one js file for each project which then I can link to a razor page. If this is possible with the CLI service please let me know.

EDIT: This is my folder structure:

wwwroot
 - vue
    - package.json
    - webpack.config.js
    - ts.config.js
    ...
    - src
        - project1
            - main.ts
            - App.vue
            - shims-vue.d.ts
        - project2
            ...
    - dist
        - project1.js
        - project2.js

Solution

  • Well, it turns out I just needed to use the latest version of vue-loader.

    For anyone else having the same issue, change this:

    "vue-loader": "^15.9.8",
    

    to this:

    "vue-loader": "^16.8.3",