「被框架玩坏的孩子们」浏览器环境下使用require

1,895 阅读2分钟

引题

常使用框架的孩子们,想要引入一个包时候,通常操作是:

  • npm i xxx
  • Vue/React组件里通过import/require 引入
  • 可以使用了

某天,当你正在欢乐地写一个html页面时,忽然想使用一个包。于是你向往常一样

  • npm init
  • npm i xxx
  • 在页面里import/require引入

这时却发现报错了。

image.png

WHY?

首先要清楚JS有两种运行环境:浏览器环境和Node.js环境

像module/exports/require属于CommonJS语法,CommonJS是Node.js采用的模块化规范,而浏览器环境下不支持该语法,所以没有这些变量。

所以,其报错原因就是因为浏览器下****没有这些定义好的变量。

模块化

换句话说,只要浏览器环境下存在这些变量,我们就能正常使用require

下面是一个简单的例子,可以跑在浏览器环境下并正常输出。

 const module = {
   exports: {}
 };
const require = (fileModule) => fileModule.exports;

// 创建一个虚拟文件
function createInventFile(module, exports) {
  exports.double = (num) => num * 2;
  return module
}
const file = createInventFile(module, module.exports);

const { double } = require(file);
console.log(double(4));

如何运行在不同环境

如何跑在浏览器环境?

  • 创建一个html,在script标签里写
  • 直接打开浏览器控制台,输入js代码

image.png

如何跑在Node环境?

  • 终端输入node,进入node环境,输入js代码
  • 创建一个x.js,终端node x.js 运行

以上代码跑在Node下会报错,因为module等变量都是已定义

image.png

browserify

其实,工具browserify已经帮我们实现了以上操作,可以在浏览器下愉快的使用模块化。

  • npm init
  • npm i -D browserify
  • browserify index.js -o compiled.index.js 编译为浏览器可识别的文件
  • 页面引入

添加npm包

有两种方法可以在浏览器环境下使用npm包

  • 把包下载到项目中,引入脚本
  • 引入cdn

使用Node模块,如child_process/fs

想在浏览器环境下使用这些模块?不存在的。

前面的browserify仅仅是将CommonJS的模块加载机制转化为浏览器可以理解的代码,所以我们能够像在Node下一样在浏览器环境下使用exports和require。

但这不意味着,我们可以任意使用Node.js模块代码。比如fs,浏览器本身是有沙箱限制的,并不允许我们任意操作本地文件,这与其安全机制背道而驰。然而chrome 83版本开始,在用户授权的情况下,允许浏览器读写用户本地文件了,有兴趣的同学参考这篇文章

怎么办?

使用node写一个服务,单独执行。与可执行文件一起打包。打开页面得时候,运行个批处理服务器。


欢迎关注我的其他账号~

博客:blog.escript.cn/

掘金:猪是倒着读着

知乎:猪是倒着读着

公众号:炸鸡呀

image.png