Compartiendo código entre proyectos usando TypeScript y webpack
Quiero compartir código entre dos proyectos de TypeScript. No quiero publicar el código compartido en NPM, solo quiero poner el código compartido en un proyecto y usarlo en otro proyecto. Estoy usando Webpack y awesome-ts-loader. La estructura actual de carpetas (simplificada) es así:
/devroot/
mainProject/
tsconfig.json
src/
shared/
SomeSharedTypes.ts
apiProject/
tsconfig.json
webpack.config.js
src/
UseSomeSharedType.ts
En UseSomeSharedType.ts, quiero poder importar tipos de SomeSharedTypes.ts.
Intenté una solución obvia como esta:
import {SharedType} from '../../mainProject/src/shared/SomeSharedTypes'
Pero el compilador de TS me dio este error:
TS6059: El archivo '/devroot/mainProject/src/shared/SomeSharedTypes.ts' no está bajo 'rootDir' '/devroot/apiProject'. Se espera que 'rootDir' contenga todos los archivos fuente.
Respuesta #1
La primera idea que obtuve de este artículo de Medium fue usar la función de importaciones de módulos no relativas de TypeScript. Esto me permitiría escribir mis importaciones así:
import {SharedType} from '@foo/SomeSharedTypes'
Usando las técnicas descritas en el artículo, agregué una configuración paths a mi tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@foo/*": ["../mainProject/src/shared/*"],
},
"rootDir": "./",
...
}
}
Luego, nuevamente como recomienda el artículo, para los usuarios de awesome-typescript-loader, tuve que modificar mi webpack.config.js para agregar un plugin de resolución:
const { TsConfigPathsPlugin } = require('awesome-typescript-loader');
. . .
resolve: {
extensions: ['.js', '.json', '.ts'],
plugins: [
new TsConfigPathsPlugin(),
],
}
Importante: este complemento debe ir en la sección resolve/plugins del archivo, ¡no en la sección de nivel raíz "plugins"! Si colocas el complemento del resolvedor en el lugar incorrecto, obtendrás este error:
resolver.ensureHook no es una función
Los pasos anteriores me hicieron avanzar más en el proceso-- ¡TypeScript ahora podía encontrar mis archivos!--pero todavía obtenía el mismo error más adelante en la ejecución de webpack: 'rootDir' se espera que contenga todos los archivos fuente.
Después de buscar mucho más en Google, encontré una solución en esta respuesta de StackOverflow: en lugar de una única configuración rootDir, TS tiene una configuración rootDirs que permite múltiples raíces. Eliminé mi configuración rootDir de tsconfig.json y agregué una configuración rootDirs:
"rootDirs": [
"./",
"../mainProject",
],
A continuación, me encontré con un error de webpack en el archivo TypeScript del otro proyecto que estaba incluyendo:
Fallo al analizar el módulo: Token inesperado (3:15)
Es posible que necesite un cargador adecuado para manejar este tipo de archivo.
Después de otra hora resolviendo problemas, descubrí que necesito informar al cargador de webpack sobre mi nueva carpeta compartida. Así:
const path = require('path');
. . .
rules: [
{
test: /\.[jt]sx?$/,
loader: "awesome-typescript-loader",
include: [
__dirname,
path.resolve(__dirname, "../mainProject/src/shared/")
],
exclude: /node_modules/
},
¡Eso funcionó! La parte agradable de esta solución es que puedo refactorizar la estructura de mi carpeta sin cambiar el código fuente. Todo lo que necesitaría cambiar es tsconfig.json y webpack.config.js.
Admito que soy nuevo usando webpack y TypeScript, así que puede que haya una mejor solución que la anterior... ¡pero la anterior funcionó para mí!
Compartiendo la solución aquí para que sea más fácil para el próximo desarrollador encontrarla.
