Estoy tratando de importar un tema desde un módulo CSS pero TypeScript me da un error "No se puede encontrar el módulo" y el tema no se aplica en tiempo de ejecución. Creo que hay algún problema con la configuración de mi paquete web, pero no estoy seguro de dónde está el problema.
Estoy usando las siguientes herramientas:
"typescript": "^2.0.3"
"webpack": "2.1.0-beta.25"
"webpack-dev-server": "^2.1.0-beta.9"
"react": "^15.4.0-rc.4"
"react-toolbox": "^1.2.3"
"node-sass": "^3.10.1"
"style-loader": "^0.13.1"
"css-loader": "^0.25.0"
"sass-loader": "^4.0.2"
"sass-lint": "^1.9.1"
"sasslint-webpack-plugin": "^1.0.4"
Aquí está mi webpack.config.js
var path = require('path');
var webpack = require('webpack');
var sassLintPlugin = require('sasslint-webpack-plugin');
module.exports = {
entry: [
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/dev-server',
'./src/index.tsx',
],
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: 'http://localhost:8080/',
filename: 'dist/bundle.js',
},
devtool: 'source-map',
resolve: {
extensions: ['.webpack.js', '.web.js', '.ts', '.tsx', '.js'],
},
module: {
rules: [{
test: /\.js$/,
loader: 'source-map-loader',
exclude: /node_modules/,
enforce: 'pre',
}, {
test: /\.tsx?$/,
loader: 'tslint-loader',
exclude: /node_modules/,
enforce: 'pre',
}, {
test: /\.tsx?$/,
loaders: [
'react-hot-loader/webpack',
'awesome-typescript-loader',
],
exclude: /node_modules/,
}, {
test: /\.scss$/,
loaders: ['style', 'css', 'sass']
}, {
test: /\.css$/,
loaders: ['style', 'css']
}],
},
externals: {
'react': 'React',
'react-dom': 'ReactDOM'
},
plugins: [
new sassLintPlugin({
glob: 'src/**/*.s?(a|c)ss',
ignoreFiles: ['src/normalize.scss'],
failOnWarning: false, // Do it.
}),
new webpack.HotModuleReplacementPlugin(),
],
devServer: {
contentBase: './'
},
};
y mi App.tsx
donde estoy tratando de importar:
import * as React from 'react';
import { AppBar } from 'react-toolbox';
import appBarTheme from 'react-toolbox/components/app_bar/theme.scss'
// local ./theme.scss stylesheets aren't found either
interface IAppStateProps {
// No props yet
}
interface IAppDispatchProps {
// No state yet
}
class App extends React.Component<IAppStateProps & IAppDispatchProps, any> {
constructor(props: IAppStateProps & IAppDispatchProps) {
super(props);
}
public render() {
return (
<div className='wrapper'>
<AppBar title='My App Bar' theme={appBarTheme}>
</AppBar>
</div>
);
}
}
export default App;
¿Qué más se requiere para habilitar la importación de módulos de hojas de estilo con seguridad de tipos?
fuente
Aquí hay una configuración completa que funciona para mí (acabo de pasar una hora de doloroso ensayo y error en esto, en caso de que alguien tenga los mismos problemas):
TypeScript + WebPack + Sass
webpack.config.js
module.exports = { //mode: "production", mode: "development", devtool: "inline-source-map", entry: [ "./src/app.tsx"/*main*/ ], output: { filename: "./bundle.js" // in /dist }, resolve: { // Add `.ts` and `.tsx` as a resolvable extension. extensions: [".ts", ".tsx", ".js", ".css", ".scss"] }, module: { rules: [ { test: /\.tsx?$/, loader: "ts-loader" }, { test: /\.scss$/, use: [ { loader: "style-loader" }, // to inject the result into the DOM as a style block { loader: "css-modules-typescript-loader"}, // to generate a .d.ts module next to the .scss file (also requires a declaration.d.ts with "declare modules '*.scss';" in it to tell TypeScript that "import styles from './styles.scss';" means to load the module "./styles.scss.d.td") { loader: "css-loader", options: { modules: true } }, // to convert the resulting CSS to Javascript to be bundled (modules:true to rename CSS classes in output to cryptic identifiers, except if wrapped in a :global(...) pseudo class) { loader: "sass-loader" }, // to convert SASS to CSS // NOTE: The first build after adding/removing/renaming CSS classes fails, since the newly generated .d.ts typescript module is picked up only later ] }, ] } };
También ponga un
declarations.d.ts
en su proyecto:// We need to tell TypeScript that when we write "import styles from './styles.scss' we mean to load a module (to look for a './styles.scss.d.ts'). declare module '*.scss';
Y necesitará todo esto en sus
package.json
dependencias de desarrollo:"devDependencies": { "@types/node-sass": "^4.11.0", "node-sass": "^4.12.0", "css-loader": "^1.0.0", "css-modules-typescript-loader": "^2.0.1", "sass-loader": "^7.1.0", "style-loader": "^0.23.1", "ts-loader": "^5.3.3", "typescript": "^3.4.4", "webpack": "^4.30.0", "webpack-cli": "^3.3.0" }
Luego, debe obtener un
mystyle.d.ts
próximo quemystyle.scss
contenga las clases CSS que definió, que puede importar como un módulo de TypeScript y usar así:import * as styles from './mystyles.scss'; const foo = <div className={styles.myClass}>FOO</div>;
El CSS se cargará automáticamente (se inyectará como un
style
elemento en el DOM) y contendrá identificadores crípticos en lugar de sus clases CSS en el .scss, para aislar sus estilos en la página (a menos que los use:global(.a-global-class) { ... }
).Tenga en cuenta que la primera compilación fallará siempre que agregue clases CSS o las elimine o les cambie el nombre, ya que mystyles.d.ts importado es la versión anterior y no la nueva versión que se acaba de generar durante la compilación. Simplemente compile de nuevo.
Disfrutar.
fuente
global.d.ts
a misrc
directorio junto con mover el ts-loader debajo de los cargadores de estilo lo arregló para mí.Aviso si está utilizando la configuración de ruta tsconfig.json
Tenga en cuenta que si está utilizando estas soluciones junto con las rutas tsconfig para acortar su importación, necesitará una configuración adicional.
Si usa una ruta tsconfig como tal:
{ "compilerOptions": { "paths": { "style/*": [ "src/style/*" ], } } }
Entonces puedes hacer:
import { header } from 'style/ui.scss';
Luego, también debe agregar una configuración de resolución de módulos en su paquete web como tal:
module.exports = { ... resolve: { ... alias: { style: path.resolve(__dirname, 'src', 'style') } } }
Asegúrese de que la ruta esté configurada de acuerdo con su configuración.
Esto hace que webpack sepa dónde buscar, ya que cree que la nueva ruta de importación es en realidad un módulo, por lo que se establece de forma predeterminada en el directorio node_modules. Con esta configuración, sabe dónde buscar y la encuentra y la construcción funciona.
fuente