Solve the problem that project migration vite introduces image resource report require is not defined


foreword

Vite is a lightweight and fast front-end construction tool that can significantly improve the front-end development experience, and the official version v4 has been released, which is relatively stable. I encountered a problem in the process of migrating the project built by VueCli to Vite. Let me share the problem and solution.

1. Problems encountered

scriptThe image resources introduced in the tag did not take effect, and then I looked at the console, and the error message showed that require is not defined ...

![Insert picture description here](https://img-blog.csdnimg.cn/c0585e98a0884fc1b40923f3ff2cedab.png

Two, the solution

1. Clear direction

After searching Vite-related documents, I saw the official document static resource processing directory, and found that this method is needed new URL()to process dynamically imported URLs, so as to ensure that image resources still point to the correct address after packaging and resource hashing.

insert image description here

2. Solutions

① Option 1

That being the case, then directly change to new URL().
Originally written as:

url: require("../assets/images/[email protected]"),
  • Then use new URL()the writing method:
url: new URL(`../assets/images/[email protected]`, import.meta.url).href;
  • or as importwritten in:
import banner from "../assets/images/[email protected]";

url: banner,

② Option 2

Since it is too troublesome to modify the above methods one by one, and the project pictures are located src/assets/images/below, it should be much more convenient to directly encapsulate it into a function and call it like hooks.

  1. Create a new useImgUrl.js file under the utils file, it is simple, just need to pass in the image file name and type
const getImgUrl = file => {
    
    
  return new URL(`../assets/images/${
      
      file}`, import.meta.url).href;
};
export default getImgUrl;
  1. Introduced and used in the file, the modification in the file only needs to use the global replacement function
import getImgUrl from "../utils/useImgUrl";

url: getImgUrl("[email protected]"),

③ Option 3

Although the above solutions do not need to be changed one by one, Vue3 does not have mixinssuch a method that can be imported globally. It still needs to introduce hooks in different files. At this time, I wonder if it is possible to process files globally webpacklike this , so that the global replacement operation is handed over. I can automatically execute it for the build tool, and then found that there is no configuration in Vite, but fortunately, a Vite plug-in gave me inspiration at this time, and I can use the Vite plug-in API to achieve similar functions, so I changed my mind and wrote such a plug-inloader.vueloader

  1. code:
// requireToUrlPlugin.js
export default function requirePlugin() {
    
    
  return {
    
    
    // 插件名称
    name: "vite-plugin-vue-requireToUrlPlugin",

    // 默认值post:在 Vite 核心插件之后调用该插件,pre:在 Vite 核心插件之前调用该插件
    // enforce: "post",

    // 代码转译,这个函数的功能类似于 "webpack" 的 "loader"
    transform(code, id, opt) {
    
    
      const vueRE = /\.vue$/;
      const require = /require/g;
      
      // 过滤掉非目标文件
      if (!vueRE.test(id) || !require.test(code)) return code;

      // 匹配 require() 内的内容
      const requireRegex = /require\((.*?)\)/g;

      // 将 require() 内的内容替换为 new URL 的写法
      const finalCode = code.replace(requireRegex, "new URL($1,import.meta.url).href");
		
	  // 将转换后的代码返回
      return finalCode;
    },
  };
}
  1. Introduce this plugin in Vite configuration:
// vite.config.js
import requireToUrlPlugin from './src/requireToUrlPlugin';
export default defineConfig(({
     
      command, mode }) => {
    
    
    plugins: [
      vue(),
      requireToUrlPlugin(),
    ]
});

After the introduction, the require method in the project will be automatically converted to the syntax of new URL() by the plug-in, which is really the ultimate trick [doge], so that you don’t need to change files one by one, which is very trouble-free, and the plug-ins written by yourself are also easy. It is completely free to customize, and the writing method is for reference only.

insert image description here

通过查看控制台能看到通过Vite的打包运行“preview”后,图片是正常显示的。

insert image description here

查看源代码能看到原本写的 require 方法已经变成了 new URL()的方法。

3. Reasons and related principles

1. Why do you need the require method

Static resources are resources directly stored in the project, and these resources do not require us to send special requests to obtain them. For example, pictures, videos, audios, font files, css style sheets, etc. under the assets directory.
Dynamic resources are resources that need to be obtained by sending requests

Answer: Because the dynamic resources introduced by the project are treated as static resources. After being packaged, the image resources packaged in the new folder will generate a new file name, and a string of numbers will be added after the original file name, which is resource hashing, which is used for server caching. Well 静态的路径并不能匹配到新的文件名,导致无法正确的引入资源, so you need to add require. require is a node method. webpack will treat the image as a module and package it according to the rules in the configuration file. The file address obtained through the require method is the file address after the resource file is compiled.

2. Why the require method fails

Answer: Because the original project was built by VueCli, which is built on top of webpack and webpack-dev-server, the require method will be processed, while the webpackVite development environment is based on native ES Module, and the production environment is Rolluppackaged through , Rollup does not support CommonJSmodules by default, so the require method cannot be recognized.

3. Why does new URL() work?

const imgUrl = new URL('./img.png', import.meta.url).href
  • new URL(url,base)
    is used to create a new URL object:

    • url – the full URL, or just the path (if base is set)
    • base - optional base URL: if this parameter is set, and the parameter url only has a path, the URL will be generated based on this base

    One of the attributes is href, which happens to be the return value of the function!

  • import.meta
    The import.meta object contains information about the current module.
    Its content depends on its environment. In a browser environment, it contains the URL of the current script, or if it is in HTML, the URL of the current page.

4. Vite plugin introduction

The Vite plugin extends the well-designed Rollup interface with some Vite-specific configuration items. Therefore, only one Vite plugin needs to be written, and it can work for both the development environment and the production environment.


Summarize

The above is all the content. This article briefly introduces the method of importing image resources by the JavaScript module during the production and construction of Vite, and introduces the basic usage of the Vite plug-in.

If this article is helpful to you, you are welcome to [Like], and you are also welcome to [Comment] + [Favorite]!


further reading

  1. Vite Official Chinese Document | Static Resource Processing
  2. Vite Official Chinese Document | Plugin API
  3. Vue CLI | Handle static resources

Guess you like

Origin blog.csdn.net/m0_55119483/article/details/129812931