【问题标题】:How do I configure webpack to display react component with typescript如何配置 webpack 以使用 typescript 显示反应组件
【发布时间】:2020-02-26 06:22:49
【问题描述】:

所以我试图让我的节点项目呈现一个简单的反应组件,我正在使用 webpack 进行捆绑

我的 package.json 设置的主要入口点为 webpack.config.js,并有一个运行 webpack-dev-server 的 srcipt。这是我的 package.json:

{
"name": "@ruler-mobility/ruler",
"_comment": "main set to webpack's bundle file(home.tsx). this attr only explain main's purpose, delete it in the next merge ",
"main": "webpack.config.js",
"dependencies": {
    "@types/jest": "^25.1.3",
    "axios": "^0.19.1",
    "chalk": "^3.0.0",
    "compression": "^1.7.4",
    "cors": "^2.8.5",
    "errorhandler": "^1.5.1",
    "express": "^4.17.1",
    "express-session": "^1.16.2",
    "geolocation-utils": "^1.2.2",
    "jest": "^25.1.0",
    "jsonwebtoken": "^8.5.1",
    "node-sass": "^4.13.1",
    "numeral": "^2.0.6",
    "query-string": "^6.11.0",
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "ts-jest": "^25.2.1",
    "typecast": "0.0.1",
    "winston": "^3.2.1"
},
"devDependencies": {
    "@types/compression": "^1.0.1",
    "@types/concurrently": "^4.1.0",
    "@types/cors": "^2.8.6",
    "@types/errorhandler": "^0.0.32",
    "@types/express": "^4.17.1",
    "@types/express-session": "^1.15.14",
    "@types/jsonwebtoken": "^8.3.6",
    "@types/node": "^12.12.25",
    "@types/numeral": "0.0.26",
    "@types/react": "^16.9.23",
    "@types/react-dom": "^16.9.5",
    "@types/ts-nameof": "^4.2.1",
    "@types/winston": "^2.4.4",
    "@typescript-eslint/eslint-plugin": "^2.18.0",
    "@typescript-eslint/parser": "^2.18.0",
    "cache-loader": "^4.1.0",
    "concurrently": "^5.0.0",
    "dotenv-webpack": "^1.7.0",
    "eslint": "^6.8.0",
    "eslint-config-prettier": "^6.9.0",
    "eslint-config-standard": "^14.1.0",
    "eslint-import-resolver-typescript": "^2.0.0",
    "eslint-loader": "^3.0.3",
    "eslint-plugin-autofix": "0.0.9",
    "eslint-plugin-import": "^2.20.0",
    "eslint-plugin-jsx-a11y": "^6.2.3",
    "eslint-plugin-no-use-extend-native": "^0.4.1",
    "eslint-plugin-node": "^11.0.0",
    "eslint-plugin-prettier": "^3.1.2",
    "eslint-plugin-promise": "^4.2.1",
    "eslint-plugin-react": "^7.18.0",
    "eslint-plugin-react-hooks": "^1.7.0",
    "eslint-plugin-sonarjs": "^0.5.0",
    "eslint-plugin-sort-imports-es6-autofix": "^0.5.0",
    "eslint-plugin-standard": "^4.0.1",
    "eslint-plugin-switch-case": "^1.1.2",
    "fork-ts-checker-webpack-plugin": "^4.0.4",
    "jest-extended": "^0.11.4",
    "nodemon": "^1.19.2",
    "prettier": "^1.19.1",
    "ts-loader": "^6.2.1",
    "ts-nameof": "^4.2.2",
    "ts-node": "^8.6.2",
    "tsconfig-paths-webpack-plugin": "^3.2.0",
    "typescript": "^3.7.5",
    "webpack": "^4.41.6",
    "webpack-cli": "^3.3.10",
    "webpack-dev-server": "^3.10.3",
    "webpack-merge": "^4.2.2",
    "webpack-node-externals": "^1.7.2"
},
"repository": {
    "type": "git",
    "url": "git+https://bitbucket.org/ruler-mobility/ruler.git"
},
"scripts": {
    "start": "webpack-dev-server",
    "build": "webpack --mode=production",
    "lint": "eslint . --quiet --fix --ext js,jsx,ts,tsx",
    "test": "jest --forceExit --coverage --verbose",
    "watch-test": "npm run test -- --watchAll",
    "stop-win": "Taskkill /IM node.exe /F",
    "stop-linux": "killall node"
},
"version": "1.0.0"
 }

我的 webpack.config.js 将 Home.tsx 设置为要捆绑的内容和输出文件在父文件夹中的路径的入口点。这是它的外观:

const path = require('path');
const chalk = require('chalk');
const merge = require('webpack-merge');
const Dotenv = require('dotenv-webpack');
 const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
 const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
 const nodeExternals = require('webpack-node-externals');
 const tsNameof = require('ts-nameof');
 const { PORT } = process.env;

module.exports = (env = {}, argv = {}) => {
const { mode } = argv;
const production = mode === 'production';
const development = !production;

console.log(
    chalk.blue(`The current build process is running in ${chalk.underline((production ? 'production' : 'development').toUpperCase())} mode`)
);

return merge(
    {
        devtool: production ? 'eval' : 'cheap-module-eval-source-map'
    },
    development && {
        optimization: {
            removeAvailableModules: false,
            removeEmptyChunks: false,
            splitChunks: false
        },
        output: {
            pathinfo: false
        }
    },
    {
        context: __dirname,
        target: 'node',
  externals: [nodeExternals()],
  //set the entry point to our app(the front-end)
        entry: path.resolve(__dirname, './front-end/components/Home.tsx'),
        module: {
            rules: [
                {
                    test: /\.tsx?$/,
                    use: [
                        'cache-loader',
                        {
                            loader: 'ts-loader',
                            options: {
                                transpileOnly: true,
                                happyPackMode: true
                            }
                        },
                        {
                            loader: 'eslint-loader',
                            options: {
                                fix: true,
                                quiet: true,
                                // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
                                getCustomTransformers: () => ({ before: [tsNameof] })
                            }
                        }
                    ],
                    exclude: /node_modules/
                }
            ]
        },
        plugins: [new Dotenv(), new ForkTsCheckerWebpackPlugin({ checkSyntacticErrors: true })],
        resolve: {
            extensions: ['.js', '.jsx', '.ts', '.tsx'],
            plugins: [
                new TsconfigPathsPlugin({
                    configFile: 'tsconfig.json'
                })
            ]
  },
  // output set's the path for front-end bundle file
        output: {
    path: path.resolve(__dirname, 'front-end/dist'),
            filename: 'home.js'

        },
        devServer: {
            contentBase: path.join(__dirname, 'front-end/dist'),
            compress: true,
            open: true,
            hot: true,
            port: PORT || 3000
        }
    }
);
 };

所以我希望 webpack 将我的文件(包括我的 Home.tsx 使用的所有内容)捆绑到名为 home.jsfront-end/dist 目录中

这是我设置Home 的方法。我在路径front-end/index.html 有一个索引html,其中包含:

<body>
    <div class="container"></div>
    <h1>Hello</h1>
    <script src="/front-end/dist/home.js"></script>
</body>

还有我的 Home.jsx:

import * as React from 'react';
import * as ReactDOM from 'react-dom';

const ROOT = document.querySelector('.container');
ReactDOM.render(<h1>HELLO 2</h1>, ROOT);

当我运行 npm run script start 并打开 localhost:3000 时,我的浏览器会显示 front-end/dist 目录中的所有文件,即 home.js 文件。它不应该加载 Home.tsx 文件,因为这是我在 webpack 中设置的入口点。如何将 webpack 配置为在根目录(即 localhost:3000)显示“home.tsx”。

在这里加上我的 tsconfig 文件:

 {
"compilerOptions": {
    "alwaysStrict": true,
    "module": "commonjs",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "jsx": "react",
    "lib": ["es6", "dom"],
    "target": "es6",
    "noImplicitAny": true,
    "moduleResolution": "node",
    "sourceMap": true,
    "skipLibCheck": true,
    "baseUrl": ".",
    "paths": {
        "*": ["node_modules/*"],
        "@ruler": ["src", "packages"],
        "@ruler/*": ["src/*", "packages/*"],
        "@ruler/configs": ["configs"],
        "@ruler/configs/*": ["configs/*"],
        "@ruler/test": ["test"],
        "@ruler/test/*": ["test/*"],
        "@ruler/types": ["types"],
        "@ruler/types/*": ["types/*"]
    }
},
"exclude": ["node_modules", "**/*.spec.ts"]
}

文件结构:

 Project
       |
       +-- package.json
       |    
       +-- tsconfig.json
       |   
       +-- webpack.config.js
       |   
       +-- front-end 
       |           |  
                   +-- components
                   |            |
                   |             +-- Home.tsx
                   |
                   +--index.html

注意:这些只是用于设置的文件,项目包含更多但我不需要提及它们

【问题讨论】:

  • 是Home.tsx,上面我解释设置webpack的entry属性的时候已经提到了。
  • 那你应该检查文件的扩展名是Home.jsx?

标签: reactjs typescript webpack configuration


【解决方案1】:

在我看来,您指的是错误的文件。因为您提到了.tsx 文件,但您的实际文件是.jsx 文件。所以我觉得你应该添加.jsx

entry: path.resolve(__dirname, './front-end/components/Home.jsx')

或者您应该将文件重命名为 Home.tsx

【讨论】:

  • 它被命名为 Home.tsx,如果它是一个命名错误,那么 webpack 会抛出错误,即找不到文件 home.tsx
  • 对。请检查 reemy 的另一个答案。
【解决方案2】:

首先,如果您需要在 webpack 配置中添加 typescript 支持,您需要添加“.ts”和“.tsx”作为可解析的扩展名,并为 ts 文件支持添加特定的加载器规则。

 resolve: {
        extensions: [".ts", ".tsx"]
    },
 module: {
        rules: [
            {
                test: /\.ts(x?)$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: "ts-loader"
                    }
                ]
            },
            // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
            {
                enforce: "pre",
                test: /\.js$/,
                loader: "source-map-loader"
            }
        ]
    },

你的 home.js 是 webpack 在转换你的入口文件后生成的捆绑文件作为输出,入口文件将是你的 Home.jsx 或 Home.tsx。

【讨论】:

  • 别忘了安装所需的节点依赖:npm install --save-dev typescript ts-loader source-map-loader
  • 所以我的 webpack 确实支持 Typescript 并且我已经安装了依赖项,我在运行 npm run script start 之前运行了 npm run script build。
  • 你能把你的文件结构交给我们吗?
  • 我已经分享了文件结构
  • 好的,你得在你的前端文件夹下添加一个dist文件夹,把你的index.html移到dist目录下
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-26
  • 1970-01-01
  • 2018-07-31
  • 2021-02-18
  • 2020-10-11
  • 2021-12-08
  • 1970-01-01
相关资源
最近更新 更多