Con la palabra "export" consigues exponer algún miembro del 
módulo, para que se pueda usar desde fuera. Con la palabra "import" 
consigues traerte algo exportado por un módulo independiente.
Aunque 
lo cierto es que seguro que muchos de vosotros ya venís usando módulos 
desde hace años, apoyándose en transpiladores como Babel, la novedad es 
que hoy ya podemos usarlos en la mayoría de los navegadores. Safari, 
Chrome, Opera ya los pueden usar de manera nativa y Firefox y Edge 
también los tienen implementados, aunque todavía hay que activarlos en 
la configuración del navegador (aunque posiblemente cuando leas este 
artículo también los puedas usar sin necesidad de configurar nada).
En este artículo te explicaremos cómo usar "ES6 modules" y como exportar e importar cosas entre distintos módulos. 
Cómo usar un módulo desde un archivo HTML
Lo primero que hay que decir es que debes hacer una acción especial 
para que el navegador procese correctamente los archivos Javascript que 
usan módulos. Básicamente se trata de advertir al navegador que el 
script Javascript usa módulos, para lo que necesitas traerte ese código 
desde el HTML usando una sintaxis especial en la etiqueta SCRIPT. 
Simplemente tenemos que marcar con type="module" el script que queremos 
incluir.
<script src="index.js" type="module"></script>
A partir de este momento, en index.js ya puedes usar imports de otros módulos, tal como explicaremos seguidamente.
Compatibilidad en navegadores antiguos
El
 uso de este "type" es importante, no solo porque así te aseguras que 
puedes usar ES6 modules, sino porque puedes implementar alternativas 
para diversos navegadores. Aunque el soporte es nativo en las recientes 
versiones de browsers, es obvio que los módulos no van a funcionar en 
todos los navegadores viejos o poco actualizados (léase los IE 
antiguos). Para ellos podemos disponer de una alternativa.
De 
momento, debes percibir que no todos los navegadores entenderán qué es 
un type="module". Al no saber qué tipo de script es un "module", los 
navegadores antiguos simplemente no harán nada con él. Es lógico, pues 
aunque lo abrieran no lo podrían entender.
Para los navegadores 
viejos hay que seguir transpilando, con Babel o similares y creando 
alternativas de scripts que no usen módulos ES6.
En resumen:
    Los navegadores modernos
 entenderán el atributo "nomodule", por lo tanto no accederán a este 
script, porque sabrán que es un script pensado por y para los 
navegadores obsoletos.
    Los navegadores antiguos no entenderán el atributo "nomodule", pero tampoco le harán caso y cargarán este script alternativo.
Como hemos dicho, usamos la sentencia export para permitir que otros módulos usen código del presente módulo. 
Con
 un export puedes exportar todo tipo de piezas de software, como datos 
en variables de tipos primitivos, funciones, objetos, clases. Ahora 
vamos a comenzar viendo un caso sencillo de hacer un export, luego 
veremos más alternativas.
export const pi = 3.1416;
Simplemente anteponemos la palabra export a aquello que queremos exportar hacia afuera.
En el momento que queramos cargar alguna cosa de un módulo externo, usaremos la sentencia import. Para ello tenemos que indicar qué es lo que queremos importar y la ruta donde está el módulo que contiene aquello que se desea importar.
import { pi } from './pi-module.js';Así 
estamos importando la anterior constante definida "pi", que estaba en un
 archivo aparte, en un módulo llamado "pi-module.js". Observarás por la 
ruta que pi-module.js está en la misma ruta que el archivo desde el que 
importamos.
Una vez importado ese dato (lo que sea que se 
importe) lo podemos usar como si la declaración hubiera sido hecha en 
este mismo archivo.
Un módulo es un archivo de JavaScript que agrupa funciones, clases, variables que luego pueden ser exportadas y utilizadas en otras partes de nuestra aplicación. Un módulo permite ocultar funcionalidad del mismo y solo exportar aquello para lo que ha sido implementado.
Esta característica agregada a JavaScript nos permite implementar programas mucho más ordenados y facilita la reutilización del código.
Veamos un ejemplo donde implementamos un módulo y luego lo consumimos:
modulo1.js
export function sumar(x,y) {
  return x+y;
}
export function restar(x,y) {
  return x-y;
}
El módulo consta de 2 funciones exportadas, podría haber dentro del módulo otras funciones, clases, variables etc. sin la palabra export que solo se pueden acceder dentro del módulo.
Para consumir un módulo desde otro módulo o una página HTML debemos utilizar la palabra clave import:
<!DOCTYPE html>
<html>
<head>
  <title>Ejemplo de JavaScript</title>
  <meta charset="UTF-8">
</head>
<body>
<script type="module">
  import {sumar, restar} from './modulo1.js';
  alert(sumar(3,8));
  alert(restar(10,3));
</script>  
</body>
</html>
Luego de la palabra clave import indicamos entre llaves los nombres de las funciones, clases, variables, constantes etc. que importamos, también debemos indicar entre comillas el nombre del módulo y el path o dirección donde se almacena (con ./ indicamos que se encuentra en la misma carpeta):
  import {sumar, restar} from './modulo1.js';
Una vez importado los recursos del paquete los podemos acceder por su nombre:
alert(sumar(3,8));
Es muy importante indicarle al navegador que estamos utilizando la nueva tecnología de módulos asignando a la propiedad type el valor de 'module':
<script type="module">
Para exportar recursos de un módulo podemos utilizar otra sintaxis:
function sumar(x,y) {
  return x+y;
}
function restar(x,y) {
  return x-y;
}
export {sumar, restar};
En un principio se definen dos funciones privadas al módulo y luego mediante la palabra clave export y entre llaves indicamos los nombres de las funciones a exportar.
Es una práctica común en JavaScript crear módulos que exporten un único valor. En estos casos tenemos una sintaxis distinta para indicar el recurso a exportar mediante las palabras claves 'default export'.
Veamos un ejemplo donde almacenamos en un módulo la clase Dado y la exportamos por defecto:
dado.js
export default class Dado {
  constructor() {
    this.tirar();
  }
  
  get valor() {
    return this._valor;
  }
  
  tirar() {
    this._valor=Math.trunc(Math.random()*6)+1;
  }
}
Luego cambia la sintaxis cuando tenemos que importar la clase:
<!DOCTYPE html> <html> <head> <title>Ejemplo de JavaScript</title> <meta charset="UTF-8"> </head> <body> <script type="module"> import Dado from './dado.js'; const dado1 = new Dado(); alert(dado1.valor); dado1.tirar(); alert(dado1.valor); </script> </body> </html>
No debemos indicar entre llaves el recurso a importar (si las disponemos se genera un error sintáctico):
import Dado from './dado.js';
Otra práctica común es no indicar el nombre de la clase en el módulo, luego el nombre del módulo representa la clase:
export default class {
  constructor() {
    this.tirar();
  }
  
  get valor() {
    return this._valor;
  }
  
  tirar() {
    this._valor=Math.trunc(Math.random()*6)+1;
  }
}
Hemos indicado export default para la clase, luego el archivo se llama 'dado.js' y representa dicha clase. No hay cambios para hacer uso de la clase:
import Dado from './dado.js';
Un módulo solo puede exportar por defecto un solo recurso pero puede tener otros recursos que se exportan. Veamos un ejemplo:
export default class{
  constructor() {
    this.tirar();
  }
  
  get valor() {
    return this._valor;
  }
  
  tirar() {
    this._valor=Math.trunc(Math.random()*6)+1;
  }
}
export const lados=6;
En éste módulo se exporta por defecto la clase y además se exporta una constante llamada lados.
Para consumir los dos valores exportados por este módulo tenemos la siguiente sintaxis:
<!DOCTYPE html>
<html>
<head>
  <title>Ejemplo de JavaScript</title>
  <meta charset="UTF-8">
</head>
<body>
<script type="module">
  import Dado, {lados} from './dado.js';
  const dado1 = new Dado();
  alert('valor del dado:'+dado1.valor);
  alert('lados del dado:'+lados);
</script>  
</body>
</html>
Importamos la clase por defecto y la constante lados:
  import Dado, {lados} from './dado.js';
Si un módulo tiene varios recursos definidos con la palabra clave export luego los podemos importar a todos juntos utilizando la siguiente sintaxis:
<script type="module"> import * as operacion from './modulo1.js'; alert(operacion.sumar(3,8)); alert(operacion.restar(10,3)); </script>
Importamos el módulo1.js que tiene dos funciones export y definimos luego de la palabra clave as el nombre de un objeto que tendrá como propiedades los recursos expotados por dicho módulo.
Llamamos ahora a cada función antecediendo el nombre del objeto creado:
alert(operacion.sumar(3,8));
Otra sintaxis para importar un recurso definido con 'export default' es mediante la sintaxis:
<!DOCTYPE html>
<html>
<head>
  <title>Ejemplo de JavaScript</title>
  <meta charset="UTF-8">
</head>
<body>
<script type="module">
  import {default as Dado, lados} from './dado.js';
  const dado1 = new Dado();
  alert('valor del dado:'+dado1.valor);
  alert('lados del dado:'+lados);
</script>  
</body>
</html>
Utilizamos la palabra clave default y seguidamente el nombre o alias que se asigna al recurso importado (debe ir entre llaves como cuando importamos valores definidos con 'export'):
  import {default as Dado, lados} from './dado.js';
Un módulo que importa un recurso puede reexportar el mismo. Veamos un ejemplo con dos módulos y el archivo html:
dado.js
export default class{
  constructor() {
    this.tirar();
  }
  
  get valor() {
    return this._valor;
  }
  
  tirar() {
    this._valor=Math.trunc(Math.random()*6)+1;
  }
}
export const lados=6;
juegodedados.js
import Dado, {lados} from './dado.js'
export class JuegoDeDados {
  constructor() {
    this.dado1=new Dado();
    this.dado2=new Dado();
    this.dado3=new Dado();
  }
  sumaDados() {
    return this.dado1.valor+this.dado2.valor+this.dado3.valor;
  }
}
export {lados};
El módulo 'juegodedados.js' importa la clase por defecto 'Dado' y la constante 'lados'. Luego este módulo exporta la clase JuegoDeDados y reexporta 'lados':
export {lados};
pagina1.html
<!DOCTYPE html>
<html>
<head>
  <title>Ejemplo de JavaScript</title>
  <meta charset="UTF-8">
</head>
<body>
<script type="module">
  import {JuegoDeDados, lados} from './juegodedados.js';
  const juego=new JuegoDeDados();
  alert('suma de los tres dados:'+juego.sumaDados());
  alert('lados del dado:'+lados);
</script>  
</body>
</html>
Como vemos solo importamos el módulo 'juegodedados.js' y recuperamos la clase JuegoDeDados y lados:
 import {JuegoDeDados, lados} from './juegodedados.js';
No hace falta importar el módulo 'dado.js' para acceder a la constante 'lados'.
Si en el módulo 'juegodedados.js' no haremos uso de la constante 'lados' pero queremos reexportar la misma podemos utilizar ésta otra sintaxis:
import Dado from './dado.js'
export class JuegoDeDados {
  constructor() {
    this.dado1=new Dado();
    this.dado2=new Dado();
    this.dado3=new Dado();
  }
  sumaDados() {
    return this.dado1.valor+this.dado2.valor+this.dado3.valor;
  }
}
export {lados} from './dado.js';