Wuzzle,进行基于 webpack 的 JS 转译

转译器(transpiler)是指能够进行文件到文件一对一转换的编译器(compiler)。在 JS 世界中,常见的开箱即可用的转译器有 typescript clibabel cli 等,但他们一般只处理 .js.ts 等脚本文件。而 webpack 尽管能通过配置处理各种文件,但他更关注如何打包 JS,做文件一对一转换相当麻烦。

为了解决这些局限,wuzzle 作为配置 webpack 编译的补充者,提供了基于 webpack 封装的 JS 转译命令 wuzzle transpile,以下是具体用法。

使用 wuzzle transpile 转译 .ts 文件

首先,我们看下 wuzzle transpile.ts 文件的转译。初始化一个空目录 demo,并安装 wuzzle:

$ mkdir demo
# ...
$ cd demo
# ...
$ npm init -y
# ...
$ npm i -D wuzzle

src/server.ts 准备一份简易服务器代码,并安装所需依赖:

import express from 'express';

const port = process.env.PORT ?? '5000';

const app = express();

app.get('/', (req, res) => {
  res.send('<!DOCTYPE html><html><head></head><body>Hello, wuzzle!</body></html>');
});

app.listen(port, () => console.log(`Started on port ${port}.`));
$ npm i -S express
# ...
$ npm i -D @types/express

默认情况下 wuzzle transpile 的转译行为等同于零配置的 webpack,几乎不做任何事情,需要安装 webpack 处理 .ts 文件所需依赖并进行配置。

因此,安装 typescriptts-loader,借助 tsc --init 创建 tsconfig.json

$ npm i -D "ts-loader@^7.0.5" "typescript@~4.6.0"
# ...
$ npx tsc --init
Created a new tsconfig.json with: # ...

然后,在 package.json 旁创建文件 wuzzle.config.js 配置 wuzzle transpile

module.exports = (webpackConfig) => {
  webpackConfig.module = {
    rules: [
      {
        test: /\.ts$/,
        loader: 'ts-loader',
      },
    ],
  };
  webpackConfig.resolve = {
    extensions: ['.ts', '.js', '.json'],
  };
};

同时,方便起见,在 package.json 写入启动脚本和构建脚本:

  "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1"
+    "start": "node dist/server",
+    "build": "wuzzle transpile \"src/**/*\" -d dist"
  },

现在,执行 build 脚本,就可以通过 wuzzle transpile.ts 文件转译成 .js 文件了:

$ npm run build
Start compiling 'src/**/*.ts'.
File 'src/server.ts' compiled.
All files compiled.

转译完成之后,通过 start 脚本,就可以启动这个服务器了,访问 http://localhost:5000,就可以看到运行效果了:

$ npm start
# ...
Started on port 5000.

使用 wuzzle transpile 转译图片文件

接下来我们再看下 wuzzle transpile 对其他文件的转译,比如图片。其实这和转译 .ts 文件类似,都是把输入文件按照指定配置转换成 .js 文件,不同的只是输入文件是图片。

这里,使用 url-loader 处理图片,安装一下依赖:

$ npm i -D url-loader

调整 wuzzle.config.js

  webpackConfig.module = {
    rules: [
      {
        test: /\.ts$/,
        loader: 'ts-loader',
      },
+      {
+        test: /\.jpg$/,
+        loader: 'url-loader',
+      },
    ],
  };

然后,放入图片 src/logo.jpg,并在 src/server.ts 引用:

import express from 'express';
+import logo from './logo.jpg';

...

app.get('/', (req, res) => {
-  res.send(`<!DOCTYPE html><html><head></head><body>Hello, wuzzle!</body></html>`);
+  res.send(`<!DOCTYPE html><html><head></head><body><img src="${logo}" /></body></html>`);
});

为了 TS 类型检查能够正确识别图片文件,创建文件 src/modules.d.ts

declare module '*.jpg' {
  const o: string;
  export default o;
}

现在,关闭正在运行的 npm start、重新执行 npm run buildnpm start、刷新 http://localhost:5000,就可以看到转译图片文件并引用的运行效果了。

优化与调试

不难发现,dist 目录下的构建产物存在两个小问题:1 是大小没有压缩过,2 是没有生成 source map。这可以在 package.json 的构建脚本中添加参数 -p-s 进行优化:

  "scripts": {
    ...
-    "build": "wuzzle transpile \"src/**/*\" -d dist"
+    "build": "wuzzle transpile \"src/**/*\" -d dist -p -s"
  }

另外,还有个开发体验上的小问题,每次修改 src 下的文件要重新手动的构建和启动。这可以结合参数 -wnodemon 来解决。

先在 package.json 写入 watch 脚本:

  "scripts": {
    ...
+    "watch": "wuzzle transpile \"src/**/*\" -d dist -w -s"
  },

watch 脚本会进行一次完整的构建后监视 src/**/* 以重新构建变化的文件。其中,参数 -s 用于生成 source map。

之后,安装 nodemon 以及另一个辅助命令行工具 concurrently 并在 package.json 写入 dev 脚本:

$ npm i -D nodemon concurrently
  "scripts": {
    ...
+    "dev": "concurrently \"npm:watch\" \"nodemon dist/server -d 2 -w dist\""
  }

dev 脚本会并行执行 watch 脚本和 nodemon 命令,当 src 目录下有文件变化时 dist 目录下对应文件就会被重新构建,而这就会让服务器重新启动。这样,在调试时就可以用 dev 脚本获得一个更好的开发体验了。

什么时候用 wuzzle transpile

如果要转译的输入文件主要是 .js.ts 等脚本文件,typescript cli、babel cli 也许就够用了。但如果遇到像示例中的那样要转译图片或者其他非脚本类文件的情况,wuzzle transpile 会是个很不错的选择。

典型的场景比如做 SSR(服务端渲染)的时候,浏览器端已经配置好了 webpack 打包,服务端就可以复用同一个配置通过 wuzzle transpile 做 JS 转译,让浏览器端代码被无缝的引用到服务端。同时,相比于在服务端复用同一个配置直接进行 webpack 打包,这能够保留构建前后的目录结构,让服务端开发保持简单。

有兴趣深入的话,wuzzle 官方示例 e2e/.../react-scripts 提供了结合使用 CRA 和 wuzzle 搭建的真实应用,其中,src/server 目录实现了 SSR 可以参考。

写在最后

目前,文章中的示例工程已经收录在了 wuzzle-blog/.../demo,读者朋友可以按需打开参考,有任何疑问或想法,欢迎留言。此外,如果对 wuzzle 有任何疑问或想法,欢迎在 wuzzle/issues 新建 issue,中英文都可以。如果有兴趣和时间贡献代码,欢迎提交 PR,具体可以参考开发引导。最后,如果觉得小工具有帮助,可以在 GitHub repo wuzzle 点个小 ⭐️,比心。

更多阅读

Wuzzle,不 eject 也能定制 create-react-app 创建的 React 应用

认真写点好代码。

2.2k 声望
1.1k 粉丝
0 条评论
推荐阅读
Transpile Webpack Plugin:让 Webpack 按照源文件的目录结构输出
作为 Web 开发者,你是否也纠结过如何用 Webpack 做文件转译?就像 Babel CLI 转译文件那样按照源文件的目录结构输出?如果有,那么这篇文章就是为你而写,我们一起瞧一瞧怎么做吧。

乌柏木5阅读 928

正则表达式实例
收集在业务中经常使用的正则表达式实例,方便以后进行查找,减少工作量。常用正则表达式实例1. 校验基本日期格式 {代码...} {代码...} 2. 校验密码强度密码的强度必须是包含大小写字母和数字的组合,不能使用特殊...

寒青57阅读 8.6k评论 11

JavaScript有用的代码片段和trick
平时工作过程中可以用到的实用代码集棉。判断对象否为空 {代码...} 浮点数取整 {代码...} 注意:前三种方法只适用于32个位整数,对于负数的处理上和Math.floor是不同的。 {代码...} 生成6位数字验证码 {代码...} ...

jenemy49阅读 7.3k评论 12

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs42阅读 7k评论 12

封面图
CSS 绘制一只思否猫
欢迎关注我的公众号:前端侦探练习 CSS 有一个比较有趣的方式,就是发挥想象,绘制各式各样的图案,比如来绘制一只思否猫?思否猫,SegmentFault 思否的吉祥物,是一只独一无二、特立独行、热爱自由的(&gt;^ω^&lt...

XboxYan48阅读 3.3k评论 14

封面图
「多图预警」完美实现一个@功能
一天产品大大向 boss 汇报完研发成果和产品业绩产出,若有所思的走出来,劲直向我走过来,嘴角微微上扬。产品大大:boss 对我们的研发成果挺满意的,balabala...(内心 OS:不听,讲重点)产品大大:咱们的客服 I...

wuwhs32阅读 3.5k评论 5

封面图
还在用 JS 做节流吗?CSS 也可以防止按钮重复点击
举个例子:一个保存按钮,为了避免重复提交或者服务器考虑,往往需要对点击行为做一定的限制,比如只允许每300ms提交一次,这时候我想大部分同学都会到网上直接拷贝一段throttle函数,或者直接引用lodash工具库

XboxYan35阅读 2.7k评论 2

封面图

认真写点好代码。

2.2k 声望
1.1k 粉丝
宣传栏