package.json
{
"name": "react-webpack-typescript-init"."version": "1.0.0"."description": "react webapck typescript"."main": "src/index.tsx"."repository": "[email protected]:zoushijun/react-webpack-typescript-init.git"."author": "zsj <[email protected]>"."license": "MIT"."scripts": {
"dll": "./node_modules/.bin/webpack --config ./config/webpack/webpack.dll.js"."build": "./node_modules/.bin/webpack --env production --config ./config/webpack/webpack.config.js && node express.js"."start": "webpack-dev-server --env development --config ./config/webpack/webpack.config.js"
},
"dependencies": {
"react": "^ 16.12.0"."react-dom": "^ 16.12.0"."typescript": "^ 3.7.4." "
},
"devDependencies": {
"@babel/core": "^ 7.7.7"."@babel/preset-env": "^ 7.7.7"."@babel/preset-react": "^ 7.7.4"."@types/react": "^ 16.9.17"."@types/react-css-modules": "^ 4.6.2." "."@types/react-dom": "^ 16.9.4"."add": "^ 2.0.6"."add-asset-html-webpack-plugin": "^ 3.1.3"."babel-loader": "^ 8.0.6"."babel-plugin-react-css-modules": "^ 5.2.6." "."css-loader": "^ 3.4.0"."express": "^ 4.17.1"."fork-ts-checker-webpack-plugin": 4 "" ^ 4.0.0 - beta.."generic-names": "^ 2.0.1." "."happypack": "^ 5.0.1." "."html-webpack-plugin": "^ 3.2.0"."os": ^ "while"."postcss-styl": "^ 0.5.1"."shelljs": "^ 0.8.3"."style-loader": "^ 1.1.2." "."stylus": "^ 0.54.7"."stylus-loader": "^ 3.0.2." "."sugarss": "^ 2.0.0." "."ts-loader": "^ 6.2.1." "."webpack": "^ 4.41.4"."webpack-cli": "^ 3.3.10"."webpack-dev-server": "^ 3.10.1"."webpack-merge": "^ 4.2.2." "."yarn": "^ 1.21.1"}}Copy the code
The basic configuration
Initialize the project
1. Create a new project prod. Mkdir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dir dist 3 Git will not detect changes if the directory is created but not in it.
Installation project dependencies
1, yarn add react react-dom 2, yarn add webpack webpack-cli webpack-dev-server -d 3, Yarn add ts-loader source-map-loader -d (source-map-loader for easy debugging, Yarn add @types/ reacte@types /react-dom -d yarn add html-webpack-plugin -D
Establish the basic document structure of the project
1. Create SRC /index.html
<! DOCTYPE html> <html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="container"></div>
</body>
</html>
Copy the code
2, the newly built. / SRC/index. The TSX
import * as React from "react";
import * as ReactDOM from "react-dom";
const ROOT = document.getElementById("container");
import { HelloWorld } from "./components/HelloWorld";
ReactDOM.render(<HelloWorld firstName="Chris" lastName="Parker" />, ROOT);
Copy the code
Create helloWorld.tsx inside SRC/Components
import * as React from "react";
export interface HelloWorldProps {
firstName: string;
lastName: string;
}
export const HelloWorld = (props: HelloWorldProps) => (
<h1>
Hi there from React! Welcome {props.firstName} and {props.lastName}!
</h1>
);
Copy the code
4, create tsconfig.json and tell Webapack to find typescript files
{
"compilerOptions": {
"jsx": "react"."module": "commonjs"."noImplicitAny": true."outDir": "./dist/"."preserveConstEnums": true."removeComments": true."sourceMap": true."target": "es5"
},
"include": ["./src/**/**/*"]}Copy the code
5. Create webpack.config.js
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.tsx",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
},
devtool: "source-map",
mode: "development",
resolve: {
extensions: [".js".".ts".".tsx"]
},
module: {
rules: [
{
test: /\.tsx? $/, loader:"ts-loader"
},
{ enforce: "pre".test: /\.js$/, loader: "source-map-loader" }
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src"."index.html")]}});Copy the code
6, modify the package. The json
"build": "./node_modules/.bin/webpack"
Copy the code
7. Run YARN Run build
Webpack hot update
Install dependencies
1. Yarn add webpack-dev-server -d
Modify the package. The json
"start:dev": "webpack-dev-server"
Copy the code
Add webpack.config.js configuration
devServer: {
port: 3001,
hot: true
},
module: {
rules: [
{
test: /\.tsx? $/, loader:"ts-loader"
}
// include: path.resolve(__dirname, "./src"),
// exclude: "./node_modules/",
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src"."index.html")
}),
new webpack.HotModuleReplacementPlugin()
]
Copy the code
error
1, Property ‘hot’ does not exist on type ‘Module’
Solution: Use the following methods:
if ((module as any).hot) {}
Copy the code
Use CSS, and use localized CSS
1. Install dependencies
Yarn add style-loader CSS-loader stylus-loader stylus babel-plugin-react-CSs-modules -d 2, yarn add happypack -d (parallel TSX file) 3, Yarn add babel-loader -d (to use babel-plugin-react-CSS-modules) 4, yarn add generic-names -d (to generate name) 5, Yarn add OS -d 6, yarn add @babel/core -d 7, yarn add fork-ts-checker-webpack-plugin -d (use typescript with happypack)
Modify the webpack. Config. Js
const path = require("path");
const webpack = require("webpack");
const genericNames = require("generic-names");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const os = require("os");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
const HappyPack = require("happypack");
const happyThreadPool = HappyPack.ThreadPool({
size: os.cpus().length
});
const stylModuleRegex = /\.cssmodule\.styl$/;
const localIdentName = "[name]__[local]-[hash:base64:5]";
const generateScope = genericNames(localIdentName, {
context: process.cwd()
});
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
require.resolve("style-loader"),
// MiniCssExtractPlugin.loader,
{
loader: require.resolve("css-loader"),
options: cssOptions
}
];
if (preProcessor) {
loaders.push(require.resolve(preProcessor));
}
return loaders;
};
module.exports = {
entry: "./src/index.tsx",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
},
devtool: "inline-source-map",
mode: "development",
resolve: {
extensions: [".tsx".".ts".".js".".styl"]
},
devServer: {
port: 3001,
hot: true
},
module: {
rules: [
{
oneOf: [
{
test: stylModuleRegex,
use: getStyleLoaders(
{
importLoaders: 1,
modules: true,
camelCase: "dashes",
getLocalIdent({ resourcePath }, localIdentName, localName) {
return generateScope(localName, resourcePath); }},"stylus-loader")}, {test: /\.css$/,
include: path.resolve(__dirname, "./src"),
use: ["style-loader"."css-loader"]}]}, {test: /\.tsx? $/, include: path.resolve(__dirname,"./src"),
exclude: [path.resolve("./node_modules/")],
use: ["happypack/loader? id=happybabel"]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src"."index.html")
}),
new webpack.HotModuleReplacementPlugin(),
new ForkTsCheckerWebpackPlugin(),
new HappyPack({
id: "happybabel",
loaders: [
{
loader: "babel-loader",
options: {
// babelrc: false,
// configFile: false// Set the cache cacheDirectory:true,
exclude: [path.resolve("./node_modules/")],
plugins: [
[
"react-css-modules", {// Generate CSS name style generateScopedName:"[name]__[local]-[hash:base64:5]",
filetypes: { ".styl": { syntax: "sugarss" } },
webpackHotModuleReloading: true,
exclude: ".css$"
}
]
]
}
},
{
loader: "ts-loader",
options: {
happyPackMode: true, / /disable type checker - we will use it in fork plugin
transpileOnly: true
}
}
],
threadPool: happyThreadPool
})
]
};
Copy the code
error
1. An error message is displayed indicating CSS-loader options
After checking the CSS-loader documentation, modify the csS-loader configuration in webpack.config.js as follows
{
test: stylModuleRegex,
use: getStyleLoaders(
{
importLoaders: 1,
modules: {
getLocalIdent({ resourcePath }, localIdentName, localName) {
return generateScope(localName, resourcePath); }}},"stylus-loader")},Copy the code
2 DetailHTMLProps error
Solutions: Yarn add @types/ react-csS-modules-d 2: styleName has been converted to styleName. That is, there is a problem with the styleName configuration
3 without importing at least one styleSheet
import "./index.cssmodule.styl";
Copy the code
2 Add it in tsconfig.json
Import * as React from React to import React from React and babel-plugin-react-csS-modules without importing at least one stylesheet."allowSyntheticDefaultImports": true."moduleResolution": "node"."module": "esNext"
Copy the code
4 not find module sugarss
5 Type ‘{ first: true; }’ is not assignable to type ‘IntrinsicAttributes & HelloWorldProps
The reason:
if ((module as any).hot) {
(module as any).hot.accept("./components/HelloWorld.tsx".function() {
console.log("Accepting the updated printMe module!");
console.log(111);
ReactDOM.render(<HelloWorld first
});
}
Copy the code
Solution:
if ((module as any).hot) {
(module as any).hot.accept("./components/HelloWorld.tsx".function() {
console.log("Accepting the updated printMe module!");
console.log(111);
ReactDOM.render(<HelloWorld firstName="Chris" lastName="Parker" />, ROOT);
});
}
Copy the code
Babel-plugin-react-css-modules configuration summary
The babel-plugin-react-CSS-modules package needs to be configured with babel-loader, so ts-loader is used first and then babel-loader is used. There is no problem in the process. However, there are many problems in the configuration process.
1 tsconfig.json
When tsconfig.json is configured, JSX is configured as react. There is a problem. In fact, all the tsconfig.json is converted by ts-loader, but it does not go to babel-loader. I’m going to change it to stylename and keep reporting errors.
Split webpack. Config. Js
The principle of
Use webpack-merge to differentiate between a development environment and a production environment, depending on the parameters passed in. Then the webpack. Config. Js into a public webpack.com mon. Config. Js, a development environment using webpack. Dev. Config. Js, a production environment with webpack. Prod. Config. Js, There is also webpack.config.js in the root directory
Webpack. Config. Js code
const commConfig = require("./config/webpack.common.config.js");
const devConfig = require("./config/webpack.dev.config.js");
const prodConfig = require("./config/webpack.prod.config.js");
const merge = require("webpack-merge");
module.exports = mode => {
if (mode === "development") {
return merge(commConfig, devConfig, { mode });
}
return merge(commConfig, prodConfig, { mode });
};
Copy the code
package.json
"start": "webpack-dev-server --env development"."build": "./node_modules/.bin/webpack --env production"
Copy the code
Increase the express
1. Install express YARN add express-d. 2
const express = require("express");
const app = express();
const portNumber = 3888;
const sourceDir = "dist";
app.use(express.static(sourceDir));
app.listen(portNumber, () => {
console.log(`Express web server started: http://localhost:${portNumber}`);
console.log(`Serving content from /${sourceDir}/ `); });Copy the code
3, modify the package. The json
"build": "./node_modules/.bin/webpack --env production --config ./config/webpack/webpack.config.js && node express.js".Copy the code
React, reat-dom, and other static files into DLL files
1, the newly built lib. Dep. Js
// Resource dependency package const lib = ["react"."react-dom"];
module.exports = lib;
Copy the code
New webpack. DLL. Js
/* webpack --config webpack.dll.config.js --progress */
const path = require("path");
const webpack = require("webpack");
const lib = require("./lib.dep");
const outputPath = path.join(__dirname, ".. /dll");
const shelljs = require("shelljs");
shelljs.rm("-r", outputPath);
module.exports = {
devtool: "eval",
entry: {
dllSelf: lib
},
mode: "production",
optimization: {
minimize: true
},
output: {
path: outputPath,
filename: "[name].[hash].js"/** * output.library * will be defined as window.${output.library}* In this case, it will be defined as' window.vendor_library '*/ library:"[name]"}, plugins: [new webpack.dllplugin ({/** * path * define the location generated by the manifest file * [name] parts of the entry name */ path: path.join(outputPath,"manifest.json"/** * name * DLL bundle output to that global variable * the same as output.library. */ name:"[name]",
context: __dirname
}),
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("production")]}});Copy the code
3. Reference DLL files in Pulgin of Webpack
module.exports = {
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require(".. /dll/manifest.json")
}),
new AddAssetHtmlPlugin([
{
filepath: utils.getDllPath(".. /dll"),
includeSourcemap: false}}])];Copy the code