之前的配置,在windows环境上运行没啥问题,但是在Mac上却是一堆bug,我也搞不清楚为啥,直到想到,会不会是不认识es6的语法?于是我立马配置了babel的基础
babel
yarn add babel-loader @babel/core @babel/preset-env
.babelrc
{
"presets": [
"@babel/preset-env"
]
}
webpack.config.js
module.exports = {
...
resolve: {
extensions: ['.js']
},
module:{
rules:[
{
test: /.(js)$/,
exclude: /node_modules/,
use: ['babel-loader']
},
]
}
}
如此就算配置完成了,之后就发现我的css被正常解析了,于是得出结论,果然是babel的问题,而且注意到,babel的配置优先级应该高于css来配置。 细说Babel
细化babel
此时的babel是简单的版本的,功能是有了,但是如果要兼容比较低级的版本的时候,目前的babel是不够用的,此时遇到Promise等语法,babel会将这句话原封不动的返回,这跟我们的需求大相径庭。于是我们要升级babel的方法。目前babel的升级方案有两种,一个是ployfill垫片+corejs,但是这个会污染全局环境,还有一种是按需加载,@babel/plugin-transform-runtime,这种看你的情况,默认的corejs是false,也就是默认会看是否有全局的polyfill,所以默认的安装包名是
yarn add @babel/plugin-transform-runtime @babel/runtime
但是既然都用按需加载了,肯定是默认不会有polyfill了,于是我们用
yarn add @babel/plugin-transform-runtime @babel/runtime-corejs3
.babelrc
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": 3
}
]
]
js变成ts
现在谁还用js呢,所以既然babel都有了,这不用一波ts?注意,用了ts-loaderh之后,我们只能进行基本的转义,对Promise等语法还是没有办法很好的进行兼容,所以我们还是需要babel-loader。那么现有的ts的通行方案,总共也有三种,分别是
- awesome-typescript-loader:这个好久没更新了,不考虑
- ts-loader + babel-loader + fork-ts-checker-webpack-plugin
- babel-loader + @babel/perset-typescript 现在网上的建议是老项目用第二种,新项目用第三种。我这里都是一下,以后的代码演示中还是2为主。
ts-loader + babel-loader + fork-ts-checker-webpack-plugin
yarn add ts-loader fork-ts-checker-webpack-plugin typescript -D
webpack.config.js
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin")
resolve: {
extensions: ['.tsx', '.ts', '.jsx', '.js']
},
module: {
rules: [
...
{
test: /.(tsx?|jsx?)$/,
exclude: /node_modules/,
use: [
'babel-loader',
{
loader: 'ts-loader',
options: {
transpileOnly: true //只进行编译,不进行类型检查
}
}]
}
]
},
plugins:[
new ForkTsCheckerWebpackPlugin()
]
babel-loader + @babel/perset-typescript
yarn add @babel/preset-typescript @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread typescript -D
webpack.config.js
resolve: {
extensions: ['.tsx', '.ts', '.jsx', '.js']
},
module: {
rules: [
...
{
test: /.(tsx?|jsx?)$/,
exclude: /node_modules/,
use: ['babel-loader']
}
]
},
.babelrc
{
"presets": [
"@babel/preset-env",
"@babel/preset-typescript"
],
"plugins": [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-object-rest-spread",
[
"@babel/plugin-transform-runtime",
{
"corejs": 3
}
]
]
}
但是这个没有办法类型检查,只能是tsc -w全局进行,体验不好
拆解webpack
在webpack中,有一个tree-shaking的功能,怎么开启呢,只需要在打包时候模式改成'production'即可,于是我们按照webpack文档,将文件分成webpack.config.dev.js(本地开发模式)和webpack.config.prod.js(用于上线的webpack的配置),以及原先的webpack.config.js三部分。然后将代码拆分
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const path = require('path');
const cssLoader = ()=>{
return [
process.env.NODE_ENV === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
'postcss-preset-env',
{stage: 3}
]
]
}
}
}
]
}
module.exports = {
entry: './src/index.js', //webpack入口
output: {
path: path.resolve(__dirname, 'build'),
filename: "js/[name].[contenthash:8].js"
},
module: {
rules: [
{
test: /.(js)$/,
exclude: /node_modules/,
use: ['babel-loader']
},
{
test: /.css$/,
use: cssLoader()
},
{
test: /.s[ac]ss$/,
use: [
...cssLoader(),
'sass-loader'
]
}
]
},
resolve: {
extensions: ['*','.js']
},
}
webpack.config.dev.js
const config = require('./webpack.config.js')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const path = require('path')
//这个是用来开发的时候会进行的操作
module.exports = Object.assign({}, config, {
mode: 'development',
devServer: {
port: '8080',
hot: true, //开启热更新
compress: true, //开启压缩
open: true //每次打开webpack的时候就能打开页面
},
plugins:[
new HtmlWebpackPlugin({
template: "./public/index.html"
}),
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(__dirname, './public'),
to: path.resolve(__dirname, './build'),
noErrorOnMissing:true,
globOptions: {
ignore: [
'**/index.html'
]
}
}
]
}),
]
})
const config = require('./webpack.config.js')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin');
const {CleanWebpackPlugin} = require("clean-webpack-plugin");
const path = require('path')
//这个是用于生产环境的操作
module.exports = Object.assign({},config,{
mode:'production',
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css',
}),
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(__dirname, './public'),
to: path.resolve(__dirname, './build'),
noErrorOnMissing:true,
globOptions: {
ignore: [
'**/index.html'
]
}
}
]
}),
],
})
package.json
{
"name": "webpack-demo",
"version": "1.0.0",
"main": "index.js",
"author": "xiaoznz",
"license": "MIT",
"devDependencies": {
"@babel/core": "^7.16.0",
"@babel/plugin-transform-runtime": "^7.16.0",
"@babel/preset-env": "^7.16.0",
"@babel/runtime-corejs3": "^7.16.3",
"babel-loader": "^8.2.3",
"clean-webpack-plugin": "^4.0.0",
"copy-webpack-plugin": "^9.0.1",
"cross-env": "^7.0.3",
"css-loader": "^6.5.1",
"dart-sass": "^1.25.0",
"html-webpack-plugin": "^5.5.0",
"less": "^4.1.2",
"less-loader": "^10.2.0",
"mini-css-extract-plugin": "^2.4.3",
"postcss-loader": "^6.2.0",
"postcss-preset-env": "^6.7.0",
"sass": "^1.43.4",
"sass-loader": "^12.3.0",
"style-loader": "^3.3.1",
"webpack": "^5.61.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.4.0"
},
"scripts": {
"build": "cross-env NODE_ENV=production webpack --config webpack.config.prod.js",
"start": "cross-env NODE_ENV=development webpack serve --config webpack.config.dev.js"
},
"browserslist": [
">0.2%",
"last 4 versions",
"Firefox ESR",
"not ie < 9"
]
}