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预设的作用进行了分析。
日拱一卒,功不唐捐。

相关推荐
xiao-xiang2 分钟前
jenkins-通过api获取所有job及最新build信息
前端·servlet·jenkins
C语言魔术师18 分钟前
【小游戏篇】三子棋游戏
前端·算法·游戏
匹马夕阳1 小时前
Vue 3中导航守卫(Navigation Guard)结合Axios实现token认证机制
前端·javascript·vue.js
你熬夜了吗?2 小时前
日历热力图,月度数据可视化图表(日活跃图、格子图)vue组件
前端·vue.js·信息可视化
桂月二二8 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062069 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb9 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角9 小时前
CSS 颜色
前端·css
九酒9 小时前
从UI稿到代码优化,看Trae AI 编辑器如何帮助开发者提效
前端·trae
浪浪山小白兔10 小时前
HTML5 新表单属性详解
前端·html·html5