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

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/[email protected]/dist/vue.js"></script>
    <script src="https://unpkg.com/[email protected]/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: {}
});

The way you can use ES modules in your Browser directly (as of June 2020) is thus:

  1. Use the ESM version of your dependencies (the one that has import instead of require). For example, Vue ESM version is available at: https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.0-beta.14/vue.esm-browser.js

  2. Make your browser work with the experimental importmap feature. Import maps are a new web recommendation, not yet supported in mainstream browsers. https://wicg.github.io/import-maps/#import-map In Chrome this is under chrome://flags#enable-experimental-productivity-features (latest Chrome versions moved this under chrome://flags#enable-experimental-web-platform-features)

  3. Create an importmap in your HTML file. It only works with inline <script> tags at the moment in Chrome. For example:

<script type="importmap">
{ "imports": {
  "vue":        "https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.37/vue.esm-browser.min.js",
  "vue-router": "https://cdnjs.cloudflare.com/ajax/libs/vue-router/4.0.16/vue-router.esm-browser.min.js"
} }
</script>
  1. Load your own code as an ESM module.
<script type="module" src="./main.js"></script>
  1. In your own scripts, and the scripts that you import - you can now successfully import from named modules.

Full example:

<html>
<body>
<script type="importmap">
{ "imports": {
  "vue":        "https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.37/vue.esm-browser.min.js",
  "vue-router": "https://cdnjs.cloudflare.com/ajax/libs/vue-router/4.0.16/vue-router.esm-browser.min.js"
} }
</script>
<script type="module">
import { createRouter, createWebHistory } from 'vue-router'
import { createApp } from 'vue'

const router = createRouter()

export default createApp({
  router
})
</script>
</body>
</html>