随着create-react-app,create-react-native-app,vue-cli和poi等一系列脚手架的大行其道,让很多入门级的前端工程师往往并不知道webpack最基础的原理与配置方法。
这里想用最简单的webpack4和babel7的最简单的配置方法来说明react项目的编译原理等。
怎么编译JSX
JSX应该是属于react的精髓,模版响应等都表现在此。而面试过很多人,发现他们对JSX的解析并不了解。typescript应该是很多前端工程师的装逼利器,但是他们往往不知道如何在已有的项目中使用typescript,或者说不知道jsx的编译原理。
与.vue
文件不同,JSX是在babel转译的过程当中完成。在vue项目当中,单个.vue
文件会被称为SFC(Single File Component单文件组件),样式,模版,脚本都会在一个文件内,他们是由vue-loader
转换为js代码。所以整个编译过程是在webpack的独立loader完成。
<img src="../image.png">
会编译为:
createElement('img', {
attrs: {
src: require('../image.png') // this is now a module request
}
})
而jsx的编译是在babel内通过babel-preset-react完成,它当中包含了三个独立的babel插件。
- @babel/plugin-syntax-jsx
- @babel/plugin-transform-react-jsx
- @babel/plugin-transform-react-display-name
需要在babel.config.js
中配置preset。
module.exports = {
"presets": ["@babel/preset-react"]
}
或者在package.json中配置babel对象。
"babel": {
"presets": [
"@babel/preset-react"
]
},
基于webpack是的极简配置,webpack.config.js可以如下配置,详情GITHUB原码。
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js',
},
devServer: {
contentBase: path.resolve(__dirname, 'dist'),
port: 9000,
},
module: {
rules: [
{
test: /\.js|jsx$/,
use: 'babel-loader',
exclude: /node_modules/,
},
],
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
title: 'react',
inject: true,
template: './src/index.html', // 模板地址
}),
],
};
怎么把它升级为tsx版本
如今我们知道jsx的编译是基于@babel/plugin-syntax-jsx的语法树转换。如果想把项目升级到typescript。丢掉babel是不可能的,否则会导致jsx转译失败。所以这里需要在babel的生态中使用typescript的preset。
现在的人是越来越分不清es5,es2015,es6,或者是最新的规范。如果在没有babel的项目当中,使用es6语法会导致低版本浏览器兼容性报错。
babel7使用 @babel/preset-env 作为最新的js语法规范,不需要再去管es2015
以及各种stage
的问题,可以通过browserslist
进行转换。
而 @babel/preset-typescript 则是可以用于替换掉 @babel/preset-env ,采用ts的最新语法规范进行项目开发。package.json 可以改为:
"babel": {
"presets": [
[
"@babel/preset-typescript",
{
"isTSX": true,
"allExtensions": true
}
],
"@babel/preset-react"
]
},
其中isTSX的选项是用于强制打开jsx的解析。否则,var foo = <string>bar
将会被jsx语法误解,详情GITHUB原码。
网友评论