javascriptvue.js

importing a package in ES6: "Failed to resolve module specifier "vue""


Trying to follow some Vue tutorials and I can't currently import Vue in a .js file and then import this file in my index.html. This is how I'm importing the script in my index.html:

<script src="./js/main.js" type="module"></script>

If I do this in my main.js file:

import Vue from 'vue';

I get the following error in the browser console:

Uncaught TypeError: Failed to resolve module specifier "vue". Relative references must start with either "/", "./", or "../".

If my import line to:

import Vue from '../../node_modules/vue';

Then I get a different error:

http://localhost:63342/vue-official-tutorial/node_modules/vue net::ERR_ABORTED 404 (Not Found)

What am I doing wrong?


Solution

  • UPDATE (2020-05-10)

    Using ES6 modules without Webpack


    If you are working with ES6 then you should NOT manually inserting your main.js into index.html - this will be handled by Webpack. Actually, the simplest tutorial for Vue goes like this:

    1. npm install -g vue-cli
    2. vue init webpack my_project
    3. npm run dev (and start developing - result is available on http://localhost:8080)
    4. npm run build (result is available inside the ./dist folder of your project

    Also, you should import Vue like this

    import Vue from 'vue';

    and not like this

    import Vue from '../../node_modules/vue';

    EDIT

    Okay, if you insist on going through the beginners' path and not using Webpack and single-file Vue components - then you should start like this:

    <!DOCTYPE html>
    <html lang="en">
    
      <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
        <title>My beginners project</title>
        <link rel="stylesheet" type="text/css" href="/assets/css/styles.css" />
      </head>
    
      <body>
        <div id="app">
          <router-view></router-view>
        </div>
        <!-- templates for your components -->
        <template id="login">
          <div>test</div>
        </template>
        <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
        <script src="https://unpkg.com/vue-router@3.0.1/dist/vue-router.js"></script>
        <!-- code for your components -->
        <script type="text/javascript" src="/app/login.js"></script>
        <!-- Vue Root component should be last -->
        <script type="text/javascript" src="/app/app.js"></script>
      </body>
    
    </html>
    

    And your /app/app.js will look like this:

    var badRoute = Vue.component('bad-route', {
        template: '<div id="bad_route"><h1>Page Not Found</h1><p>Sorry, but the page you were trying to view does not exist.</p></div>'
    });
    var vue_router = new VueRouter({
        base: '/app'
        , mode: 'hash'
        , routes: [{
            path: '/'
            , redirect: '/login'
        }, {
            path: '/login'
            , component: loginForm
            , name: 'LOGIN'
        }, {
            path: '*', // should be last, otherwise matches everything
            component: badRoute
            , name: 'NOT FOUND'
        }]
    });
    // Main application
    var vue_app = new Vue({
            router: vue_router
        , })
        .$mount('#app');
    

    And your /app/login.js component will look like this:

    var loginForm = Vue.component('login-form', {
        template: '#login', // should match the ID of template tag
        data: function() {
            var a = {
                username: ''
                , password: ''
            , };
            return a;
        }
        , methods: {}
    });