So lassen Sie nicht deklarative Namespaces in React with Typescript zu
Ich bin gerade in die in Typescript integrierte React-Umgebung eingestiegen. Daher verstehe ich nicht ganz, wie es intern tatsächlich funktioniert, und ich hoffe, dass zwischen den Lösungen keine Antworten fehlen.
Ich habe eine Lösung gefunden, von der ich nichts wollte https://stackoverflow.com/a/62084097/10694438Es ist ein Downgrade der Typoskript-Version und es scheint mit der Version <4 zu funktionieren. Aber ich möchte es nicht downgraden.
Der Fehler tritt auf, wenn ich ein Skript npm run buildausführe, wenn index.tsx ein benutzerdefiniertes Element enthält, dessen Klassendatei den entsprechenden Namespace enthält, z
class Foo ... {
...
}
namespace Foo {
*Some inner classes of Foo are here*
}
export default Foo;
Die Nachricht ist Namespace not marked type-only declare. Non-declarative namespaces are only supported experimentally in Babel.
Ich habe versucht, es herauszufinden https://babeljs.io/docs/en/babel-plugin-transform-typescript#impartial-namespace-support. Also habe ich versucht, eine .babelrcDatei zu erstellen und "plugins": [["@babel/plugin-transform-typescript", {"allowNamespaces": true}]]in die Datei einzufügen, aber es hat nicht funktioniert.
Meine package.json ist derzeit so (einige nicht relevante Dinge werden weggelassen):
"dependencies": {
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.3"
},
"devDependencies": {
"@types/reach__router": "^1.3.6",
"@types/react": "^16.9.49",
"@types/react-dom": "^16.9.8",
"typescript": "^4.0.3"
},
"scripts": {
"build": "react-scripts build",
},
Antworten
Ich habe versucht, mehr Lösungen zu finden, aber es scheint, dass es keine klare Lösung gibt, wenn Sie sich auf der Boilerplate der Create-React-App befinden, da ein anderes Problem auftritt, wenn ich es auf irgendeine Weise löse. Daher verlasse ich diese Lösung, bei der das Projekt selbst eingerichtet wird, ohne die App "create-react-app" zu verwenden, die ich wollte, aber aufgrund meines mangelnden Wissens über React- und Webpack-Dinge nicht ausprobieren konnte. Wirklich zu schätzen wissenhttps://youtu.be/nCoQg5qbLcY.
package.json
"scripts": {
"build": "webpack --mode production --progress",
"dev": "webpack-dev-server --mode development"
},
"devDependencies": {
"@babel/core": "^7.11.6",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/preset-env": "^7.11.5",
"@babel/preset-react": "^7.10.4",
"@types/mini-css-extract-plugin": "^0.9.1",
"@types/node": "^14.11.2",
"@types/optimize-css-assets-webpack-plugin": "^5.0.1",
"@types/react": "^16.9.49",
"@types/react-dom": "^16.9.8",
"@types/webpack": "^4.41.22",
"@types/webpack-dev-server": "^3.11.0",
"babel-loader": "^8.1.0",
"core-js": "^3.6.5",
"css-loader": "^4.3.0",
"html-webpack-plugin": "^4.5.0",
"mini-css-extract-plugin": "^0.11.2",
"optimize-css-assets-webpack-plugin": "^5.0.4",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"resolve-url-loader": "^3.1.1",
"sass": "^1.26.11",
"sass-loader": "^10.0.2",
"ts-loader": "^8.0.4",
"ts-node": "^9.0.0",
"tsconfig-paths-webpack-plugin": "^3.3.0",
"typescript": "^4.0.3",
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0"
}
Lassen Sie mich die Abhängigkeiten außerhalb des Codes für diejenigen beschreiben, die ihn kopieren und einfügen möchten.
*-loaders sind Module, die Importe in Ihre Quelldateien auflösen. Da Webpack nur Javascript-Dateien versteht, müssen Sie ihm einen Loader geben, der die importierten Dateien bestimmter Erweiterungen versteht.
html-webpack-pluginNimmt js / css-Ausgaben von Loadern und fügt sie in die von Ihnen angegebene HTML-Vorlage ein und gibt die HTML-Datei in output.pathwebpack.config aus, sodass die Stile und das gebündelte Javascript auf der Seite aktiv sind. Dies ist ein Ersatz für style-loader, da style-loaderdies nicht mit CSS-Minimierern wie funktioniert mini-css-extract-plugin.
Den Grund für Ihre Verwendung resolve-url-loaderfinden Sie hier .
optimize-css-assets-webpack-plugin Funktioniert nur mit einem CSS-Minimierer, da ein Minimierer eingebunden wird.
Einige Lader benötigen einen Transpiler, der jeder Erweiterung entspricht, sassund typescriptsind diese Instanzen.
tsconfig-paths-webpack-pluginErmöglicht Webpack die Verwendung der pathsOption in Ihrer tsconfig.
Obwohl es ohne funktioniert , core-jswie es in vielleicht enthalten ist @babel/preset-env(ich es eindeutig nicht erinnern , aber es ist wie die Version von Embedded verwenden core-jsist eine veraltete Art und Weise), ist es , weil , wenn Sie Set - useBuiltInsOption entweder usageoder entryin @babel/preset-envin babel.config.json, @babel/preset-envwird murren , dass Sie‘ d besser die Version von einstellen core-js.
ts-node wird für webpack.config.ts benötigt.
@babel/plugin-syntax-dynamic-import kann weggelassen werden, wenn Sie keine dynamischen Importe verwenden.
webpack.config.ts
import Webpack from "webpack";
import Path from "path";
import TsconfigPathsWebpackPlugin from "tsconfig-paths-webpack-plugin"; // makes webpack use the paths option in tsconfig
import HtmlWebpackPlugin from "html-webpack-plugin"; // bundles assets into one html file
import MiniCssExtractPlugin from "mini-css-extract-plugin"; // minimizes css files
import OptimizeCssAssetsPlugin from "optimize-css-assets-webpack-plugin"; // removes duplicate selectors in css files by hooking mini-css-extract-plugin loader
const factory: Webpack.ConfigurationFactory = (env, args): Webpack.Configuration => {
const outputPath = Path.resolve(__dirname, "build");
const config: Webpack.Configuration = {
context: Path.resolve(__dirname),
entry: "./src/index.tsx",
output: {
filename: "index.js",
path: outputPath // must be an absolute path
},
resolve: {
// locates modules of file or directory that are included by import(or require)
// It locates modules by their absolute paths, so every relative path gets converted into absolute path.
// If the module is a file, then it gets bundled, otherwise files of extensions in the extensions option in the directory get bundled.
extensions: [".ts", ".tsx", ".js"],
plugins: [new TsconfigPathsWebpackPlugin()] // uses the paths option in tsconfig instead of using the resolve.modules option
},
plugins: [
new MiniCssExtractPlugin({ // won't be able to use style-loader
filename: "index.css", // relative to output.filename
}),
new OptimizeCssAssetsPlugin(), // if it's in optimization.minimizer property, webpack-dev-server won't apply it.
new HtmlWebpackPlugin({
filename: "index.html", // relative to output.filename
template: "src/index.html" // relative to context
})
],
module: {
rules: [
{
test: /\.tsx?$/, exclude: /node_modules/, use: [ "babel-loader", "ts-loader" ] }, { test: /\.jsx?$/,
exclude: /node_modules/,
use: [
"babel-loader"
]
},
{
test: /\.s[ac]ss$/, use: [ MiniCssExtractPlugin.loader, "css-loader", "resolve-url-loader", "sass-loader" ] }, { test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader"
]
}
]
},
devtool: "source-map",
devServer: {
contentBase: outputPath,
watchContentBase: true,
compress: true,
port: 3000,
proxy: {
"/api": "http://localhost:8080"
},
hot: true,
stats: {
colors: true,
version: false,
hash: false,
assets: false,
timings: false,
children: false, // children are plugins that are applied to webpack like mini-css-extract-plugin
entrypoints: false,
cached: false,
cachedAssets: false,
exclude: [
/node_modules/,
/webpack/
]
}
}
};
return config;
};
export default factory;
Ich habe die Beschreibung zur besseren Lesbarkeit in den Code eingefügt. Eine Sache, die Sie vorsichtig sein sollten, ist die Reihenfolge der Laderliste bei der Verwendung . Und beachte auch, dass ich beides benutze babel-loaderund ts-loaderda du so viel weitere Konfiguration ohne brauchst ts-loader.
babel.config.json
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "entry",
"corejs": "3",
"targets": {
"browsers": [
">5%",
"not ie 11",
"not op_mini all"
]
}
}
],
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-syntax-dynamic-import", // you may delete this line
"@babel/plugin-transform-modules-commonjs"
]
Beachten Sie, dass ich nicht @ babel / ts-loaderpreset-typescript verwende, wie ich es stattdessen für Webpack verwende.
"useBuiltIns": "entry"bedeutet, dass Ihr Babel integrierte Bibliotheken verwendet, die in Browsern implementiert sind. Ich weiß nicht, ob dies dynamisch funktioniert oder ob dadurch nicht implementierte Funktionen im Internet vorinstalliert werden target browsers.
Sie müssen sie setzen import "core-js/stable"und import "regenerator-runtime/runtime"bevor die Einfuhr oder die Codes , die JavaScript - Codes in Ihrer enthaltenen entryDatei zu babel Lasten polyfills zu lassen.
import "./index.scss" // this is okay as it's just styles.
// replacements for deprecated @babel/polyfill
import "core-js/stable";
import "regenerator-runtime/runtime";
tsconfig.json
"compilerOptions": {
"watch": true,
"module": "commonjs", // for webpack, ts-node does not support any module syntax other than commonjs.
"allowSyntheticDefaultImports": true, // for webpack
"esModuleInterop": true, // for webpack
"moduleResolution": "node", // for webpack.config about @types
"target": "es6",
"jsx": "react",
// belows are in favor of your project
"baseUrl": ".",
"strict": true,
"alwaysStrict": false,
"isolatedModules": true,
"noImplicitUseStrict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"forceConsistentCasingInFileNames": true,
"experimentalDecorators": true,
"sourceMap": true,
},
"include": [
"./src/**/*",
"webpack.config.ts"
]
Die Klasse wird im Namespace definiert. Siehe Dokumentation.
Und die Klasse entspricht nicht dem Namespace.
class Foo ...
namespace nameOptional {
*Some inner classes are here*
}
export default Foo;