I’m now trying to start a new project with Phoenix 1.4.0 as it comes with Webpack by default, and I’m trying to get Typescript to work with it, which is surprisingly difficult.
I changed the file app.js
to app.ts
, and the problem I’m struggling with now is the first statement: import css from '../css/app.css';
. Apparently, from questions such as https://stackoverflow.com/questions/41336858/how-to-import-css-modules-with-typescript-react-and-webpack, and https://stackoverflow.com/questions/40382842/cant-import-css-scss-modules-typescript-says-cannot-find-module, it’s a nontrivial task to import CSS modules in Typescript… Typescript wouldn’t recognize the module which doesn’t end in .js
or .ts
.
According to the instructions in that post, I tried to create a file called typings.d.ts
:
declare module '*.css' {
interface IClassNames {
[className: string]: string;
}
const classNames: IClassNames;
export = classNames;
}
Now, Typescript doesn’t complain about the module. However, running npx webpack --mode development
doesn’t actually emit the CSS file whatsoever. webpack
just completely ignores the app.css
file.
The following is my webpack.config.js
. I only changed two places:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = (env, options) => ({
optimization: {
minimizer: [new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: false }), new OptimizeCSSAssetsPlugin({})]
},
// entry: './js/app.js',
entry: './js/app.ts',
output: {
filename: 'app.js',
path: path.resolve(__dirname, '../priv/static/js')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: 'ts-loader'
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
},
plugins: [
new MiniCssExtractPlugin({ filename: '../css/app.css' }),
new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
]
});
I think this should be fairly easy to replicate with a new project.
cd assets
npm install --save-dev typescript ts-loader
npx tsc init
- Create
typings.d.ts
in the folder - Edit
webpack.config.js
I think the problem might lie with the Typescript module declaration. Unfortunately I don’t know enough to come up with a more sensible solution. I tried to generate a module for each css file in the /css
folder with https://github.com/Quramy/typed-css-modules, but Typescript complains that assets/css/app.css.d.ts' is not a module.
Should I just give up the idea of turning app.js
into a Typescript file and try to integrate Typescript in some other fashion, e.g. wrapping it in a module which is to be imported in app.js
?