浏览器兼容-polyfill-本地服务-优化
babel和webpack结合
npx babel src --out-dir dist --presets=@babel/preset-env
这是把src下面的东西都用babel转化一下
webpack可以和babel结合使用,首先下载一个这东西:
npm install babel-loader -D
webpack配置:
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, './build'),
filename: 'bundle.js',
//重新打包时现将之前打包的文件夹删除
clean:true
},
module:{
rules:[
{
test:/.js$/,
use:{
loader:'babel-loader',
options:{
plugins:[
'@babel/plugin-transform-arrow-functions',
'@babel/plugin-transform-block-scoping'
]
}
}
}
]
}
}
要指定对应的插件才生效
如果我们一个个的去安装使用插件就需要手动管理大量的babel插件,我们可以直接给webpack提供一个preset,webpack会根据对应的预设来加载插件列表并将其传递给babel
比较常见的预设有env、react、TypeScript
安装preset-env:
npm install @babel/preset-env
浏览器兼容性
浏览器的内核都趋向于使用Blink
我们在编写css和js的时候需要考虑到浏览器的兼容性问题,但是对于前端开发者来说既要写代码又要考虑兼容性就很烦,所以急需一些工具帮助对css/js进行转化
对css进行转化的是postcss
对js进行转化的是babel
而代码要不要自动进行转化取决于要适配的浏览器,一个一个对应版本还是太麻烦了
编写一个browserslistrc配置文件可以帮助我们进行浏览器适配
也得是配让我适配的浏览器我才会给他适配
哪个热门人用的多就挑哪个
怎么知道哪个浏览器人用的多呢?看浏览器市场占有率:
"Can I use" usage tablehttps://caniuse.com/usage-table
超过百分之一的人用就需要做兼容了
写好配置就可以用Browserslist做兼容了(在不同的前端工具之间共享目标浏览器和Node.js版本的配置)
在开发中我们可以编写的条件:
配置browserslist可以配置 package.json也可以单独的一个配置文件.browserslistrc文件
没有配置也有默认配置,当编写了多个条件之后,多个条件之间的关系:
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, './build'),
filename: 'bundle.js',
//重新打包时现将之前打包的文件夹删除
clean:true
},
module:{
rules:[
{
test:/.js$/,
use:{
loader:'babel-loader',
options:{
// plugins:[
// '@babel/plugin-transform-arrow-functions',
// '@babel/plugin-transform-block-scoping'
// ]
presets:[
"@babel/preset-env",{
// 在开发中针对babel的浏览器兼容查询使用browerlist工具,而不是设置targets
targets:">5%"
}
]
}
}
}
]
}
}
推荐使用这个工具,不用targets,因为这个工具能进行统一的适配
配置的targets属性会覆盖browserslist
Stage-X的preset
ECMAScript规范定义了JavaScript如何一步步的进化、发展
TC39是指技术委员会第39号
特性的打磨发展是一步一步的:
在babel7之前(babel6中),我们经常会看到这种设置方式:
它表达的含义是使用对应的babel-preset-stage-x预设
从babel7开始不建议使用了,建议使用preset-env来设置
Babel的配置文件
我们可以将babel的配置信息放到一个独立的文件中,babel可以编写两种配置文件:
babel.config.json(或者.js , .cjs , .mjs)文件
.babelrc.json(或者 .babelrc , .js , .cjs , .mjs)文件
他们两个是由区别的:
认识polyfill
有的时候我们使用了一些语法特性,但是浏览器根本不认识这些特性必然会报错,可以使用polyfill打一个补丁,这样就包含该特性了
useBuiltlns属性设置
第三个值就是entry了
如果我们依赖的某一个库使用了某些polyfill的特性,但是我们使用的是usage之后浏览器可能就会报错
如果担心出现这样的情况可以用entry
需要在入口文件添加import 'core-js/stable'
import 'regenerator-runtime/runtime'
这样做会根据browserslist目标导入所有的polyfill,对应的包也会变大
React的jsx支持
在我们编写react代码时,react使用的语法是jsx,jsx是可以直接使用babel来转换的
对react.jsx处理需要下面的插件:
在开发中不需要一个个的安装这些插件,依然可以用preset配置
npm install @babel/preset-react -D
配置自动构建:
{
"name": "babel_core_demo",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"build": "webpack"
},
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"@babel/cli": "^7.27.2",
"@babel/core": "^7.27.4",
"@babel/plugin-transform-block-scoping": "^7.27.5",
"@babel/preset-env": "^7.27.2",
"@babel/preset-react": "^7.27.1",
"babel-loader": "^10.0.0",
"html-webpack-plugin": "^5.6.3"
}
}
然后在webpack里配置babel:
const path = require('path');
const HtmlwebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, './build'),
filename: 'bundle.js',
//重新打包时现将之前打包的文件夹删除
clean:true
},
resolve: {
extensions: ['.js', '.jsx'] // 这句告诉webpack自动尝试这两个后缀
},
module:{
rules:[
{
test:/.jsx?$/, //表示有0或者1个x
use:{
loader:'babel-loader',
options:{
// plugins:[
// '@babel/plugin-transform-arrow-functions',
// '@babel/plugin-transform-block-scoping'
// ]
presets:[
["@babel/preset-env", { targets: ">5%" }],
"@babel/preset-react"
]
}
}
}
]
},
plugins:[
new HtmlwebpackPlugin({
template:'./index.html',
filename: 'end.html'
})
]
}
这个x?已经能即处理js又处理jsx了
但是莫名其妙还是报错,加resolve是永远都搜索这俩文件
babel的配置文件:
module.exports = {
presets: [
'@babel/preset-env',
'@babel/preset-react',
],
};
模板html:
Document
index.js:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './react/App'
//const定义常量(ES6)
const message = 'Hello World';
console.log(message);
const foo = ()=>{
console.log("foo function exec!");
}
foo();
// 使用字符串中的includes方法
const nickname = 'coderwhy';
console.log(nickname.includes('why'));
const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render();
最后运行webpack就会打包并且react能成功解析运行在浏览器中了
ts-loader处理ts代码
npm install ts-loader -D
需要安装一下ts:
npm install -g typescript
然后进行初始化:
tsc --init
初始化后直接生成一个tsconfig.json
然后直接运行npm run build就可以完成编译了
使用babel-loader
除了可以使用tsc来编译TS,我们也可以使用Babel
Babel是有对TS进行支持
可以使用插件:@babel/transform-typescript
更推荐直接使用preset:@babel/preset-typescript
ts-loader和babel-loader的选择
ts-loader默认使用的是TypeScript complier
里面是不包含polyfill的
所以最好用babel-loader
使用针对ts的预设就可以解决这个问题
使用预设的好处是可以配置polyfill
module.exports = {
presets: [
['@babel/preset-env',{
corejs: 3, // 配置使用core-js的版本
useBuiltIns: 'usage', // 根据配置的浏览器兼容,以及代码中使用到的 API 进行引入 polyfill 按需加载
}
],
'@babel/preset-react',
'@babel/preset-typescript',
],
};
ts-loader会进行类型的校验,但是babel-loader就不会,所有各有各的优点
建议我们即用babel完成代码类型的转化,又使用tsc来进行类型的检查
但是我们如何使用tsc进行类型的检查呢?
我们可以在scripts中添加两个脚本用于类型检查
执行npm run ts-check可以进行ts类型检测
执行npm run ts-check-watch可以实时检测类型错误
{
"name": "babel_core_demo",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"build": "webpack",
"ts-check":"tsc --noEmit",
"ts-check-watch":"tsc --noEmit --watch"
},
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"@babel/cli": "^7.27.2",
"@babel/core": "^7.27.4",
"@babel/plugin-transform-block-scoping": "^7.27.5",
"@babel/preset-env": "^7.27.2",
"@babel/preset-react": "^7.27.1",
"babel-loader": "^10.0.0",
"html-webpack-plugin": "^5.6.3",
"ts-loader": "^9.5.2"
},
"dependencies": {
"@babel/preset-typescript": "^7.27.1"
}
}