Webpack y TypeScript: la vigilancia no funciona para las interfaces exportadas
ACT.
Tengo dos carpetas, frontend y shared, que se empaquetan con webpack usando ts-loader.
El problema es que los cambios en las interfaces exportadas desde la carpeta compartida no se detectan.
Si agrego en IThemes.ts una exportación como
export const x = 2
que los cambios se detectan nuevamente incluso para cambios en la interfaz.
ejemplo de IThemes.ts exportado:
export interface IGeneralTheme {
isDay: boolean
day: ITheme
night: ITheme
}
ejemplo de uso de interfaz ThemeContext.tsx:
import React, { useState, useEffect } from 'react'
import { deepClone, ITheme, IGeneralTheme } from '@shared'
import { ThemeProvider, createGlobalStyle } from 'styled-components'
type ThemeContextProps = {
theme: ITheme
generalTheme: IGeneralTheme
isDay: boolean
setGeneralTheme: React.Dispatch<React.SetStateAction<IGeneralTheme>>
}
export const ThemeContext = React.createContext<Partial<ThemeContextProps>>({})
tsconfig.base.json:
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true,
"sourceMap": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"removeComments": true,
"noImplicitThis": true,
"alwaysStrict": true,
"strictBindCallApply": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"allowJs": true,
"strictPropertyInitialization": true
},
"exclude": [
"../../node_modules"
]
}
tsconfig.json en la carpeta frontend:
{
"extends": "../configs/tsconfig.base.json",
"include": [
"**/*",
"../shared/**/*"
],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@shared": [
"../shared/index"
],
"@frontend": [
"index"
]
},
"jsx": "react",
"target": "es2015"
}
}
webpack.base.js:
const path = require('path')
const webpack = require('webpack')
module.exports = {
entry: '../frontend/client.tsx',
output: {
path: path.resolve('../../public'),
filename: 'react_bundle.js'
},
devtool: 'source-map',
resolve: {
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
alias: {
'@frontend': path.resolve(__dirname, '../frontend/index'),
'@shared': path.resolve(__dirname, '../shared/index')
}
},
module: {
rules: [
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader'
}
]
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
enforce: 'pre',
test: /\.js$/,
loader: 'source-map-loader'
}
]
},
plugins: [new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /ru/)]
}
webpack.dev.js:
const merge = require('webpack-merge')
const base = require('./webpack.base.js')
const webpack = require('webpack')
module.exports = merge(base, {
mode: 'development',
watch: true,
plugins: [
new webpack.DefinePlugin({
isProd: false
})
]
})
Ejecutado por comando desde la carpeta de configuraciones: npx webpack --config webpack.dev.js
Respuesta #1
Encontré la respuesta a mi propia pregunta después de ver que no funciona solo para la interfaz:
Me encontré con un problema similar. Lo que lo solucionó para mí fue cambiar los nombres de archivo de los archivos que solo contienen interfaces de *.ts a *.d.ts.
Aparentemente, el ts-loader genera salida solo para archivos que producen salida en JavaScript y archivos de definición de TypeScript. Luego, el output es leído por el observador de webpack, y webpack se actualiza si uno de estos archivos cambia.
En su caso, tiene archivos que no generan salida de JavaScript y no son archivos de definición de TypeScript. Por lo tanto, no se generará salida a partir de ellos, y el observador de webpack no notará cuando cambien.
La alternativa es awesome-typescript-loader que parece funcionar bien.
Respuesta #2
Tienes que habilitar la opción del compilador de TS importsNotUsedAsValues, consulta: https://github.com/TypeStrong/ts-loader/issues/1138