El mensaje de error «No se puede utilizar la sentencia import fuera de un módulo» se produce cuando se encuentra la palabra clave import
en un módulo JavaScript o TypeScript mal configurado.
En un entorno de ejecución del lado del servidor de JavaScript, este error suele producirse por el uso de la sintaxis import
para módulos escritos en ECMAScript (ES) cuando Node.js espera la palabra clave require
utilizada por el sistema de módulos CommonJS.
TypeScript admite diferentes formatos de módulos, pero los errores de codificación que confunden los enfoques ES y CommonJS para importar módulos también provocan este error.
En el lado del navegador, el error suele producirse cuando no utilizas un bundler para tus archivos de código JavaScript.
Este artículo explora estas tres fuentes de error y detalla una solución para cada entorno.
Cómo Resolver el Error en JavaScript del Lado del Servidor
Esta sección muestra cómo resolver el error en entornos JavaScript del lado del servidor.
Antecedentes
Node.js utiliza por defecto la palabra clave require
del sistema CommonJS. Por lo tanto, recibirás el conocido error a menos que configures Node.js para que admita la sintaxis de módulo ES. Del mismo modo, Node.js requiere la extensión .mjs para reconocer y trabajar con módulos ES.
Solución
Como alternativa al uso de .mjs, puedes hacer que las versiones antiguas de Node.js sean compatibles con el módulo ES actual utilizando bundlers o ejecutando Node.js con la bandera --experimental-modules
. Si no, podrías establecer el campo type
en el archivo package.json a module
de la siguiente manera:
{
"name": "test-package",
"version": "1.0.0",
"type": "module",
"main": "app.js",
"dependencies": { }
}
(Nota: Debes incluir la propiedad type
en el archivo package.json de todos los paquetes. Esta práctica facilita la identificación del sistema de módulos en uso y garantiza la coherencia entre tus bibliotecas)
Otra forma de evitar el error es asegurarte de que las sintaxis import
y export
son correctas y se cargan adecuadamente. Es fundamental utilizar siempre rutas de archivo relativas, exportaciones con nombre, extensiones de archivo para las exportaciones y evitar las exportaciones por defecto.
Aquí tienes un ejemplo:
//module import
import { sampleFunction } from './sampleModule.js';
// function export
export function sampleFunction() {
// code goes here
}
Por último, debes asegurarte de la compatibilidad de todas las bibliotecas de terceros con los módulos ES. Para ello, consulta la documentación de la biblioteca en el archivo package.json. Alternativamente, utiliza un bundler para transpilar el código de modo que un entorno JavaScript pueda entenderlo.
Cómo Resolver el Error en Entornos TypeScript
Esta sección muestra cómo resolver el mensaje de error en entornos TypeScript.
Antecedentes
Con los módulos, puedes reutilizar, organizar y compartir código entre varios archivos de un proyecto. ES admite módulos externos para compartir código entre varios archivos utilizando las palabras clave import
y export
.
Este error suele producirse en entornos TypeScript cuando se utiliza la sintaxis de módulos ES sin configurar TypeScript para utilizarla. Dado que TypeScript es un superconjunto de JavaScript, utiliza por defecto la sintaxis CommonJS para las importaciones, que utiliza require
en lugar de import
. En este caso, la sentencia import
provoca el error. No obstante, es necesario configurar correctamente TypeScript para que admita módulos ES.
También puedes encontrarte con este error si utilizas una extensión de archivo incorrecta. Por ejemplo, al utilizar TypeScript en un entorno Node.js con sintaxis de módulos ES, el módulo que quieras importar debe tener la extensión de archivo .mjs en lugar de la habitual .js.
Otra fuente habitual del error es la configuración incorrecta del campo module
en tus archivos tsconfig.json o package.json cuando utilizas bundlers como Webpack. Sin embargo, puedes utilizar bundlers para módulos ES en TypeScript configurando los campos module
y target
en el archivo tsconfig.json a ECMAScript
. Entonces, Webpack entenderá el entorno de destino y utilizará las extensiones de archivo correctas al transpilar el código.
Solución
Para cargar módulos ES utilizando un cargador de módulos como RequireJS o un bundler como Webpack, añade lo siguiente al archivo tsconfig.json:
{
"compilerOptions": {
"module": "es20215",
"target": "es20215",
"sourceMap": true
}
}
En la parte compilerOptions
del código anterior, los campos module
y target
están configurados para utilizar un módulo es20215
. Con estas adiciones, puedes utilizar las declaraciones import
y export
en un entorno TypeScript sin que se produzca el error.
Como TypeScript utiliza CommonJS por defecto, si no modificas el archivo tsconfig.json en consecuencia, aparecerá el mensaje de error.
Afortunadamente, una vez que hayas configurado los campos module
y target
para utilizar un módulo ECMAScript
, puedes utilizar la sentencia export
para exportar una función o variable de un módulo y la sentencia import
para cargar otro módulo en el ámbito del actual. Este proceso ocurre en el siguiente código:
// sum.ts
export function sum(a: number, b: number, c: number): number {
return a + b + c;
}
// main.ts
import { sum } from './sum';
console.log(add(4, 4, 9));
Si utilizas una versión anterior de Node.js, puedes activar la compatibilidad con módulos ES ejecutando tu código con la bandera --experimental-modules
. También debes utilizar un bundler como Webpack, Browserify o Rollup para empaquetar todo el código ES y enviarlo a un único archivo. Asegúrate de que está en una versión que los navegadores y las versiones antiguas de Node.js puedan entender y configura un archivo Webpack.config.js en el root de tu proyecto que especifique el tipo de módulo.
Aquí tienes un ejemplo extraído de la documentación de Webpack:
module.exports = {
entry: './src/index.ts',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
resolve: {
extensions: ['.ts', '.js', '.mjs']
},
module: {
rules: [
{
test: /.ts$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
experiments: {
outputModule: true
}
};
El código compilado se envía a un archivo bundle.js en el directorio dist del directorio root del proyecto.
También puedes utilizar polyfills como es-module-shims
para dirigirte a navegadores antiguos que no admiten las sentencias import
y export
de los módulos ES.
Cómo Resolver el Error en JavaScript del Lado del Navegador
Esta sección te muestra cómo resolver el error en entornos JavaScript del lado del navegador.
Entorno
La mayoría de los navegadores modernos, incluidos Chrome, Firefox, Edge y Safari, soportan módulos ES, por lo que no necesitarás utilizar polyfills, bundlers o transpiladores del navegador.
Tampoco los necesitarás si utilizas las bibliotecas frontend basadas en JavaScript React o Vue, porque admiten por defecto los campos ES imports
y exports
. Sin embargo, los navegadores más antiguos no admiten la sintaxis ES, por lo que necesitan estas herramientas para la compatibilidad entre plataformas.
La razón más frecuente del error en un navegador antiguo es cuando los archivos HTML de una página no contienen el atributo type="module"
. En este caso, el error se produce porque el JavaScript que se ejecuta en la web no incluye soporte por defecto para la sintaxis de módulos ES. Para el código JavaScript enviado a través de la red, podrías encontrarte con un error de compartición de recursos de origen cruzado (CORS) al intentar cargar un módulo ES desde un dominio diferente.
Solución
Para evitar el error de módulo en un navegador antiguo, asegúrate de que estás utilizando el atributo correcto de la etiqueta script
– type="module"
— en el archivo root HTML. Alternativamente, puedes utilizar Webpack para transpilar el código de modo que los navegadores antiguos puedan entenderlo.
Para utilizar el atributo type="module"
, incluye la siguiente línea en tu archivo root HTML:
<script type="module" src="app.js"></script>
Es igualmente importante que te asegures de que las rutas de los archivos import
son válidas y de que utilizas la sintaxis import
correcta.
Además, puedes visitar sitios como Can I Use para confirmar la compatibilidad de los navegadores con los módulos ES.
Por último, dado que el uso de la extensión de archivo .js es una práctica habitual, puedes establecer el atributo type
en la etiqueta script
del archivo HTML del módulo como solución. Establecer este atributo en module
indica al navegador que ignore la extensión .js y trate el archivo como un módulo.
Resumen
El error «No se puede utilizar la sentencia import fuera de un módulo» puede aparecer por varias razones, dependiendo de si estás en un entorno JavaScript del lado del navegador o del lado del servidor. La sintaxis incorrecta, las configuraciones inadecuadas y las extensiones de archivo no compatibles siguen siendo algunas de las fuentes más comunes de este error.
Aunque la mayoría de los navegadores modernos admiten módulos ES, debes asegurarte de que los navegadores antiguos sean compatibles. Bundlers como Webpack te permiten compilar todo el código fuente con sus dependencias en una única salida que los navegadores antiguos puedan entender.
Recuerda añadir el atributo type="module"
en el archivo HTML para informar al navegador de que el módulo es un módulo ES. Por último, aunque utilizar la extensión .js para CommonJS es la práctica por defecto, puedes utilizar la extensión .mjs para permitir la importación de módulos ES.
¿Tienes una aplicación JavaScript que necesitas poner online pero no quieres gestionar tú mismo los servidores? Las plataformas de Alojamiento de Aplicaciones y Alojamiento de Bases de Datos de Kinsta podrían ser la respuesta. Incluso puedes combinar estos servicios con el Alojamiento de Sitios Estáticos de Kinsta para que el front-end de tu aplicación se sirva gratuitamente.