Code前端首页关于Code前端联系我们

Vue2 中出现 require is not defined 是怎么回事?该怎么解决?

terry 2天前 阅读数 20 #Vue

在Vue2开发过程中,不少同学会遇到“require is not defined”的报错,这个问题乍一看有点懵,但拆开分析其实和「运行环境」「构建工具」「代码写法」这几个关键点有关,接下来咱们一步步搞清楚:为啥会出现这个错误?不同场景下该怎么解决?

先搞懂:require是啥?浏览器为啥不认识它?

首先得明确require是Node.js的模块化语法——Node.js环境里,用require('模块名')来导入其他JS文件/第三方库;用module.exportsexports,但浏览器原生不支持require!因为浏览器的模块化方案是后来才有的ES模块(用import/export),和Node.js的CommonJS规范不一样。

那Vue2项目里为啥会碰到这个报错?常见两种情况:

  1. 代码在浏览器环境直接运行(比如CDN引入Vue的纯HTML项目),但写了Node.js风格的require
  2. 用了构建工具(如webpack、vite),但配置不对/代码写法不兼容,导致require没被正确处理。

场景1:Vue单文件组件里引入资源时报错

很多人在.vue文件里引入图片、JS模块时踩坑,这时候得看你用的是webpack系工具(如vue-cli)还是vite,因为两者对require的支持逻辑不同。

子场景A:用vue-cli(基于webpack)的项目

vue-cli默认集成webpack,而webpack会把CommonJS语法(如require)转换成浏览器能懂的代码,但要注意这几点:

  • 路径要写对:比如引入src/assets下的图片,得用require('@/assets/logo.png')(是webpack配置的src别名),要是路径错了,webpack找不到文件,就会报错;
  • 资源要被loader处理:vue-cli默认装了url-loaderfile-loader来处理图片、字体等资源,如果自己手动改了webpack配置,得确保loader没被删;
  • 别在“裸奔”的JS里用require:比如在index.html里直接引入一个没被webpack打包的JS文件,里面写require,浏览器肯定不认识,得确保所有用了require的文件,都被webpack纳入构建流程。

举个正确例子(在Vue组件的script里):

<template>
  <img :src="imgSrc" />
</template>
<script>
export default {
  data() {
    return {
      imgSrc: require('@/assets/logo.png') // webpack会把这行转成浏览器能识别的路径
    }
  }
}
</script>

子场景B:用vite构建的Vue2项目

vite是基于ES模块(ESM)的构建工具,默认不支持CommonJS的require语法,如果你的Vue2项目是用vite创建的(比如npm init vite@latest选Vue2模板),直接写require就会报错,这时候得换思路:

优先用ES模块的import语法

比如引入图片:

<script>
import logo from '@/assets/logo.png' // vite会处理这个导入,返回资源路径
export default {
  data() {
    return {
      imgSrc: logo
    }
  }
}
</script>

如果是引入JS模块(比如自己写的工具函数),也得改成import

// 原来的require写法
const utils = require('./utils.js')
// 改成ES模块导入
import utils from './utils.js'
// 或者按需导入
import { formatTime } from './utils.js'

必须用require时,装插件支持

要是必须用require(比如第三方库只有CommonJS版本),可以装个插件让vite支持,比如vite-plugin-require-transform,在vite.config.js里配置:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue2'
import requireTransform from 'vite-plugin-require-transform'
export default defineConfig({
  plugins: [
    vue(),
    requireTransform({
      fileRegex: /.js$|.vue$/ // 匹配.js和.vue文件,让插件处理require
    })
  ]
})

场景2:CDN引入Vue的纯HTML项目报错

有些同学做简单Demo,直接用CDN引入Vue2,

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
  // 这里写了require,直接报错
  const myModule = require('./myModule.js')
</script>

这时候浏览器没有require,因为这是Node.js的语法,解决方法分两种:

方法1:用ES模块(浏览器支持的话)

script标签加type="module",然后用import导入:

<script type="module">
  // 注意:ES模块必须用相对路径,且被导入的文件要支持ESM
  import myModule from './myModule.js' 
  new Vue({
    el: '#app',
    // ...
  })
</script>

对应的myModule.js得用ES模块导出:

// myModule.js
export default {
  sayHi() { console.log('你好~') }
}

方法2:用全局变量引入第三方库

如果是引入axios这类第三方库,直接用CDN的全局变量版本:

<script src="https://cdn.jsdelivr.net/npm/axios@1.4.0/dist/axios.min.js"></script>
<script>
  // 此时axios是全局变量,直接用
  axios.get('https://api.example.com')
    .then(res => console.log(res))
</script>

场景3:构建工具配置错误导致require未被处理

如果你的项目用webpack/vue-cli,但依然报错“require is not defined”,大概率是webpack配置漏了对require的支持,或者文件没被webpack打包

问题1:webpack没正确处理JS文件

webpack默认支持CommonJS语法,但如果手动改了module.rules,把处理JS的babel-loader配置错了,可能导致require没被处理,检查webpack.config.js里的module.rules,确保JS文件被正确处理:

module: {
  rules: [
    {
      test: /\.js$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env'] // 转成浏览器能跑的ES版本
        }
      }
    },
    // 还要有处理图片、CSS等的loader,
    {
      test: /\.(png|jpg|jpeg|gif)$/,
      use: [
        {
          loader: 'url-loader',
          options: {
            limit: 8192 // 小图片转base64,大图片输出文件
          }
        }
      ]
    }
  ]
}

问题2:代码文件没被webpack打包

比如你在index.html里直接引入了一个main.js,但这个main.js里又用require引入其他文件,而webpack的入口配置没包含这个main.js,导致webpack没处理里面的require,浏览器直接运行就会报错,解决方法:确保webpack的entry配置正确,所有需要打包的文件都被纳入构建流程。

module.exports = {
  entry: './src/main.js', // 入口是src/main.js,webpack会从这里开始打包
  // ...
}

问题3:误用Node.js内置模块

比如在前端代码里写const path = require('path'),但path是Node.js的内置模块,浏览器里没有,所以会报错,要避免在前端代码里使用Node.js专属模块,换成前端能用的替代方案(比如处理路径用path-browserify这类库)。

分步骤排查解决

遇到“require is not defined”别慌,按这几步走:

  1. 看环境:是浏览器还是Node.js?Vue2前端项目几乎都是浏览器环境,先排除Node.js环境误用;
  2. 看工具:用webpack/vue-cli还是vite?webpack系默认支持require(但要配置对),vite默认不支持(优先用import);
  3. 换语法:静态资源(图片、CSS)在webpack用require,vite用import;JS模块统一用ES模块的import/export
  4. CDN项目:用ES模块(type="module")或者全局变量,别直接写require

其实这个问题核心是「不同环境的模块化规范不兼容」——Node.js用CommonJS(require),浏览器现代方案用ES模块(import),而构建工具是“翻译官”,帮我们在不同环境间做转换,理清这层逻辑,再结合具体场景调整代码或配置,问题就迎刃而解啦~

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门