本文章手动搭建react工程,使用hooks + ts, antd多主题,大概分为四章
新建example文件夹然后初始化package.json文件
mkdir example
cd example
yarn init // 根据提示输入
package.json就建好了
先介绍一下npm
npm脚本一般放在scripts里面,run的时候会拉起一个shell脚本跑里面的代码,npm可以串并行
-
'&' 并行执行顺序,同时执行
"dev":"node test.js & webpack"
-
'&&' 继发顺序,执行前面之后才可以执行后面
"dev":"node test.js && webpack"
在scripts中写入export DEV_HOST, 在test.js中通过process.env.DEV_HOST就可以获取到'pro',
"scripts": {
"test": "export DEV_HOST=pro && node build/test.js"
},
根目录新建build文件夹,新建test.js文件,写入
console.log('---process.env.DEV_HOST--', process.env.DEV_HOST);
然后执行 npm run test
开始安装webpack
yarn add webpack webpack-cli -D
创建以下文件目录
build
webpack.common.js
webpack.prod.js
webpack.dev.js
src
index.js
package.json
先写点简单命令
build/webpack.dev.js
const path = require('path');
module.exports = {
mode: 'development',
devtool: 'inline-source-map',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, "../dist"),
filename: "bundle.js"
}
};
src/index.js
console.log('hello')
package.json
"scripts": {
"dev": "webpack --config ./build/webpack.test.js",
},
执行npm run dev,dist目录会生成bundle.js, node bundle.js, 会打印hello
安装配置webpack-dev-server webpack-merge
yarn add webpack-dev-server webpack-merge -D
package.json
"scripts": {
"dev": "webpack ./build/webpack.dev.js",
+ "start": "export DEV_HOST=$(ifconfig | grep broadcast | awk '{print $2}') && webpack-dev-server --config ./build/webpack.dev.js",
},
(ifconfig | grep broadcast | awk '{print 2}')是mac下获取当前ip地址的命令
--config用来指定配置文件,不指定则默认为根目录下的webpack.config.js,__webpack的命令
build/webpack.dev.js
devServer: {
contentBase: './dist',
host: '0.0.0.0',
public: `${process.env.DEV_HOST || localhost}:8080`,
hot: true,
},
run起来 可以直接访问http://10.180.6.207:8080/bundle.js
安装clean-webpack-plugin html-webpack-plugin
yarn add clean-webpack-plugin html-webpack-plugin -D
clean-webpack-plugin 每次打包时清理上次打包生成的目录
html-webpack-plugin 生成打包文件中的 index.html
build/webpack.dev.js新增
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// module.exports新加
plugins: [
new HtmlWebpackPlugin(),
new CleanWebpackPlugin(),
]
拆分webpack.common.js webpack.dev.js webpack.prod.js文件
webpack.prod.js和webpack.dev.js不同的是没有devServer
package.json scripts新增
"build": "webpack --config ./build/webpack.prod.js",
build/webpack.common.js
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const resolve = p => path.resolve(__dirname, p);
module.exports = {
entry: './src/index.tsx',
output: {
filename: 'bundle.js',
path: resolve('../dist'),
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin(),
]
};
webpack-merge有个坑,4.x的时候直接引入可以使用
const merge = require('webpack-merge');
const { merge } = require('webpack-merge');
最终build/webpack.dev.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common');
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
host: '0.0.0.0',
public: `${process.env.DEV_HOST || localhost}:8080`,
hot: true,
},
});
build/webpack.prod.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common');
module.exports = merge(common, {
mode: 'production',
});
安装 react react-dom
yarn add react react-dom
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
function App() {
return (
<div>start</div>
)
}
ReactDOM.render(<App />, document.getElementById('root'));
因为react独有的jsx语法需要进行转义才能使用,转义需要用babel,先将jsx -> es6, 在将es6 -> es5
安装babel babel各个模块之间的关系
yarn add @babel/core @babel/cli @babel/preset-env -D
yarn add @babel/preset-react -D
yarn add babel-loader -D
build/webpack.common.js 新增module配置
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-react'],
}
}
],
},
],
},
由于一般babel的配置都是放在babel.config.js中,所以根目录新建babel.config.js文件并写入配置,webpack的loader配置修改
build/webpack.common.js 修改module配置
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: 'babel-loader',
},
babel.config.js
module.exports = function(api) {
const presets = [
'@babel/preset-react',
];
const plugins = [];
return {
presets,
plugins,
};
}
重新run会报错
module.exports = function(api) {
+ api.cache(true);
const presets = [
'@babel/preset-react',
];
...
api.cache(true);在babel的介绍
babel7主要就是两个包,@babel/cli和@babel/core,cli用于执行命令行,core则是babel用于解析、转换、代码生成的核心包。 如果只跑babel-loader, 不在config中加入任何presets和plugins。 解释
如果只跑babel-loader, 不在config中加入任何presets和plugins
const fun = () => {
const isarr = Array.isArray([1, 2, 3]);
console.log('---index.js---', isarr);
};
fun()
const presets = [
['@babel/preset-env', {
modules: false,
}],
];
转换后
babel默认只转语法,不转api,如果需要转换api 则需要引入babel-polyfill
用了babel还需要polyfill吗??? babel-polyfill怎么引入
安装babel-polyfill
yarn add @babel/polyfill
直接在index.js中引入
import "@babel/polyfill";
再build,本来10K的bundle变成了855K
直接引入babel-polyfill相当于直接引入
import "core-js/stable";
import "regenerator-runtime/runtime";
可以安装个 webpack-bundle-analyzer来看看webpack打包性能
yarn add -D webpack-bundle-analyzer
build/webpack.dev.js
+ const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
...
plugins: [
+ new BundleAnalyzerPlugin()
]
...
然后run start可以看到打包的文件大小
所以现在可以在babel.config.js的@babel/preset-env中加入
const presets = [
['@babel/preset-env', {
modules: false,
+ useBuiltIns: 'usage', // 实现按需加载
}],
];
webpack react已经引入了,下面就开始引入react-router loadable啦