Webpack项目构建入门:babel的核心角色

  • 作者简介:大家好,我是文艺理科生Owen,某车企前端开发,负责AIGC+RAG项目
  • 目前在卷的技术方向:工程化系列,主要偏向最佳实践
  • 希望可以在评论区交流互动,感谢支持~~~

最近在梳理webpack打包构建的相关内容,本着一起( )面对寒冬的心态,把整个思考和分析过程分享出来。各位看官有任何想法都可以在评论区留言,感谢支持~

下面的内容会按照项目从0到1搭建过程的顺序展开。

首先创建和运行一个最小的webpack项目。

创建一个最小项目

项目初始化

新建一个空文件夹,在该目录下运行 npm init -y,完成后目录下会多出一个package.json文件,用来管理npm依赖的相关配置。

安装 webpack

根目录下运行 pnpm i webpack webpack-cli -D

根目录下新建 webpack.config.js,用于管理 webpack 相关配置。

在根目录下新建 src 文件夹,在 src 目录下新建 index.js,并添加一段ES6的 js 代码:

js 复制代码
// src/index.js

const a = 1
console.log(a, 'a')

package.json文件中配置打包构建命令

json 复制代码
{
  // 其他配置...
  "scripts": {
    "dev": "webpack --mode development --config webpack.config.js"
  },
  // 其他配置...
}

根目录下运行 pnpm dev,结果输出:

js 复制代码
/dist/main.js

并在打包结果中,es6的代码未被转换:

✅已完成里程碑1:

1.最小项目的创建工作

2.运用webpack打包构建
🔖下一个里程碑2:
ES6-const代码转为ES5-var代码

Babel的使用

Babel插件使用

安装 babel: pnpm i babel-loader @babel/core -D

增加 webpack基础配置

js 复制代码
// webpack.config.js

const path = require('path')

module.exports = {
  mode: 'development', // 默认为开发环境模式
  entry: './src/index.js', // 入口文件
  output: {
    path: path.resolve(__dirname, 'dist'), // 打包后的文件路径
    filename: 'bundle.js', // 打包后的文件名
  },
  // 模块配置
  module: {
    // 以下配置含义:以.js结尾的文件均使用babel-loader
    rules: [
      {
        test: /.js$/,
        use: 'babel-loader'
      }
    ]
  }
}

在根目录下新建 babel.config.json,用来配置 babel

对应特定的语法转换,我们可以通过Babel提供的插件处理。在 Babel官网 中可以找到 const语法 对应的插件为 @babel/plugin-transform-block-scoping

安装插件 pnpm add @babel/plugin-transform-block-scoping -D

babel.config.json中使用

diff 复制代码
// babel.config.json

+{
+  "plugins": ["@babel/plugin-transform-block-scoping"]
+}

运行 pnpm dev 打包,发现 const语法 被成功转为了 ES5-var语法

✅已完成里程碑2:
将ES6-const代码转为ES5-var代码
🔖下一个里程碑3:
ES6-箭头函数代码转为ES5-function代码

index.js中新增一段 ES6-箭头函数 的代码:

diff 复制代码
// index.js

+ const fn = () => {}
+ fn()

同样方法,找到了箭头函数 对应的babel插件

安装插件 pnpm add @babel/plugin-transform-arrow-functions -D

在babel配置文件中添加这个插件:

diff 复制代码
// babel.config.json

{
  "plugins": [
      "@babel/plugin-transform-block-scoping", 
+     "@babel/plugin-transform-arrow-functions"
  ]
}

运行 pnpm dev 打包,发现 ES6-箭头函数代码转为了ES5-function代码

再对比下配置前的:

通过上面两个例子发现 :ES高版本的语法均可通过 babel插件 进行转换兼容。但如果在开发项目时,每使用一个语法,便手动安装和配置一个插件,效率太低了

✅已完成里程碑3:
将 ES6-箭头函数 代码转为 ES5-function 代码
🔖下一个里程碑4:
ES6常用代码转为ES5代码

Babel预设使用

为了解决上面的问题,Babel 推出了 preset(预设集)。这个集合里包含了常见的语法转换插件,我们来修改一下:

先移除上面两个插件:
pnpm uninstall @babel/plugin-transform-arrow-functions @babel/plugin-transform-block-scoping -D

再安装 babel预设pnpm i @babel/preset-env -D

修改babel配置,注意预设需要在 presets 下配置 ,并且对应一个二维数组

json 复制代码
// babel.config.json
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "entry",
        "corejs": "3.22"
      }
    ]
  ]
}

运行 pnpm dev 打包,转换成功。

考虑到语法转换需要消耗构建性能,通过配置目标浏览器范围可以减少不必要的损耗。

json 复制代码
{ 
  "browserslist": "> 0.05%, not dead"
}

配置说明:

  • >0.05%:全球使用率大于0.05%的浏览器
  • not dead:排除已弃用的浏览器版本,比如IE(兼容ie需要移除这条)

browserslist官网 中可以直观看到兼容范围:

✅已完成里程碑4:
将ES6常用代码转为ES5代码
🔖下一个里程碑5:
编译css代码

css代码编译

在 src目录 下新建 index.css 文件,添加一段 css 代码:

css 复制代码
body {
  color: red;
}

并在 index.js 中导入

diff 复制代码
// index.js

+ import './index.css'

运行 pnpm dev 打包,出现报错css代码无法被识别

对于特定的语法格式,我们需要借助于 loader 进行转换。css 语法对应的 loader 为 css-loader

安装css-loaderpnpm i css-loader -D

配置 webpack:

js 复制代码
// webpack.config.js

// 其他代码
module.exports = {
  module: {
    rules: [
      {
        test: /.css$/,
        use: 'css-loader'
      }
    ]
  }
}

运行 pnpm dev 打包,报错消失 ,并且在输出文件中可以看到 css代码

思考:在实际项目中,如果所有js代码和css代码共存于一个文件中,项目构建后的文件体积很大,每次变更都需要重新下载,下载时间长

如果可以将css文件和js文件拆分 ,使其并行下载 ,并且css文件采用缓存策略,可以提高性能。

✅已完成里程碑5:
编译css代码
🔖下一个里程碑6:
拆分css构建文件

css构建文件拆分

我们可以通过一个webpack插件mini-css-extract-plugin来将css代码单独提取到一个单独的文件中。

安装插件:pnpm i mini-css-extract-plugin -D

修改 webpack 配置

js 复制代码
// webpack.config.json

const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
  module: {
    rules: [
      {
        test: /.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin()
  ]
}

运行 pnpm dev 打包,完成后 dist目录下多了一个 main.css的文件,它就是被提取出的css代码文件。

并且在 bundle.js文件中无法搜索到css代码,说明 css代码提取成功。

✅已完成里程碑6:
拆分css构建文件
🔖下一个里程碑7:
编译typescript代码

编译typescript代码

安装typescriptbabel-typescript预设pnpm i @babel/preset-typescript typescript -D

在 src目录 下新建 index.ts,增加ts代码

ts 复制代码
// index.ts

const a: number = 1

console.log(a);

修改webpack配置

js 复制代码
// webpack.config.js

module.exports = {
  // 其他代码
  entry: './src/index.ts', // 入口文件更改为index.ts
  module: {
    rules: [
      {
        test: /.(j|t)s$/, // 增加ts文件规则,使用babel进行编译
        use: 'babel-loader'
      }
    ]
  }
}

修改babel配置

json 复制代码
// babel.config.json

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "entry",
        "corejs": "3.22"
      }
    ],
    "@babel/preset-typescript"  // 添加ts预设
  ]
}

运行 pnpm dev 打包,构建完成。

✅已完成里程碑7:
编译typescript代码
🔖下一个里程碑8:
编译tsx代码

编译tsx代码

分别安装 reactbabel-react预设:
pnpm i react
pnpm i @babel/preset-react -D

在 src目录下 新建 Title.tsx,用来表示一个 react标题组件

tsx 复制代码
// Title.tsx

import React from 'react'

const count: number = 1
export const Title = () => <div>标题{count}组件</div>

并在index.ts文件中引入

ts 复制代码
// index.ts

import {Title} from './Title.tsx'

console.log(Title);

修改webpack配置

js 复制代码
// webpack.config.js

module.exports = {
  // 其他代码
  module: {
    rules: [
      {
        test: /.(j|t)sx?$/,  // 目标文件增加 jsx和tsx类型
        use: 'babel-loader'
      }
    ]
  },
}

修改babel配置

json 复制代码
// babel.config.json

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "entry",
        "corejs": "3.22"
      }
    ],
    "@babel/preset-typescript",
    "@babel/preset-react"  // 增加react预设
  ]
}

运行 pnpm dev 打包,构建完成

tips如果在index.ts中引入组件文件时,省略了后缀名,则构建时会报错

解决方式:

在webpack配置中,增加后缀类型

js 复制代码
// webpack.config.js

module.exports = {
  // 其他代码
  resolve: {
    extensions: ['.tsx']  // 如果有其他文件类型,可手动添加
  }
}

✅已完成里程碑8:
编译typescript代码

✅✅✅恭喜你完成了全部的里程碑✅✅✅
总结:本文通过从零开始搭建一个最小的Webpack项目,解决了诸如ES6代码转换css代码编译与拆分优化ts代码编译tsx代码编译等问题,重新梳理在成熟的cli框架中如何采用babel进行语法编译转换,并对babel预设的作用进行了分析。
日拱一卒,功不唐捐。

相关推荐
崔庆才丨静觅11 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606112 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了12 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅12 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅13 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅13 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment13 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅13 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊13 小时前
jwt介绍
前端
爱敲代码的小鱼13 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax