preface
- I wrote that before
vite
δΈvue2
Integrated articles, just call himπ Vue2. X retrofit β‘οΈ Vite –1.0
- Time flies, more than a month has passed and a certain degree of accumulation of a part of the new posture, need to
1.0
Make some improvements and additions; Then write the2.0
2.0
Mainly forvite
Integrate and do somethingMining pit guide, and1.0
It doesn’t matterPlease eat directly
π’ Note: It is only recommended to run vite in development mode in the production environment as before; Webpack, after all, is more sophisticated in packaging
Project background
- The transformation project is a very important, iterative and frequent system of the company; It now has over 100 pages
- Engineering formwork by
@vue/cli
To create thevue2.x
Version for internal usewebpack4.x
build - As projects get bigger (50 pages per year or so), the need for a cold start becomes more pressing
Technical analysis
-
While Vite is growing fast, NPM plugins for Vite are also catching on fast; But there was always something out of reach in our old projects
-
Here I mainly with my actual transformation of the problems encountered to do the technical summary, if you have encountered other problems in the process of use, this article to solve the problem ideas also have a certain reference value
-
The following are the transformation problems I encountered (for vue2 project generated by @vue/ CLI)
- The default project root directory entry is required
index.html
Point to existingpublic/index.html
- Convert CSS notation
@import '~normalize.css/normalize.css
In the~
The alias - eliminate
import('@/pages/' + path)
Written in vite warning β οΈ - conversion
require
δΈΊimport
Syntax —- CommonJs to ESModule - The compatible webpack
require.contex
grammar - support
<script>
Write in code blockjsx
Syntax —- render returns JSX
- The default project root directory entry is required
vite plugins
-
First, the project was modified based on an official plugin, Vite-plugin-vue2
npm i -D vite-plugin-vue2 Copy the code
-
You might want to know how to write a Vite plugin first
Point index.html to public/index.html
-
Plug-in vite – plugin – HTML – the template
npm i -D vite-plugin-html-template Copy the code
-
Quote from vite’s official website
You may have noticed that in a Vite project, index.html is in the outermost layer of the project instead of in the public folder. This is intentional: Vite is a server during development, and index.html is the entry file for that Vite project.
-
The principle of analytic
- In development mode
vite
All resources are passedhttp server
Return to before browsingindex.html
There is no exception
This means that we can intercept/and /index.html requests through the plugin’s configureServer and then read public/index.html and return it
{ name: 'vite-vue2:html'.configureServer(server) { server.middlewares.use((req, res, next) = > { // Intercepts/or /index.html requests if (req.url === '/' || req.url === '/index.html') { const html = fs.readFileSync(path.join(__dirname, 'public/index.html'), 'utf8') / / return public/index. HTML res.end(html) } else { next() } }) }, } Copy the code
- In build mode we need to touch a new concept virtual file
-
Official Demo π introduces a virtual file
-
We use load to properly load public/index.html in build mode
{ name: 'vite-vue2:html'.load(id) { if (id.endsWith('index.html')) { const html = fs.readFileSync(path.join(__dirname, 'public/index.html'), 'utf8') / / return public/index. HTML return html } }, } Copy the code
-
XDM might say why not load index.html via config.root;
-
The root directory of the vue2 project is the source directory, and index. HTML appears as source code, not as a static file
-
Changing config.root to public causes many other problems; For example, @/views/home.vue is intended to find/SRC /views/home.vue
-
π index.html is the entry file for the Vite project
- In development mode
Convert CSS notation@import '~normalize.css/normalize.css
In the~
The alias
- This is a
vite
More powerful parts, support the use ofresolve.alias
Official note π Vite path aliases also comply with CSS - Pit!!!!!!: only recognize
alias/xxxx
Don’t recognizealiasxxxx
- You have the following configuration
{ resolve: { alias: { The '@': path.join(__dirname, 'src'), '~': path.join(__dirname, 'node_modules'), // This is usually used for CSS import}}}Copy the code
- They will be
@/xxxx
,~/xxxx
Hit,But not by@xxxx
,~xxxx
hit - A lot of people have this when they write CSS
@import '~normalize.css/normalize.css';
—- This inability to hit - You need to write it like this
resolve: { alias: [ // For @xxxx and @/ XXXX { find: The '@'.replacement: path.join(__dirname, 'src')},/ / ~ / XXXX { find: ~ / / * * // ^ ~? = \ /), replacement: path.join(__dirname, 'node_modules')},/ / ~ XXXX { find: / * ~ * // ^ ~? ! / / /), replacement: path.join(__dirname, 'node_modules/')},]},Copy the code
- You have the following configuration
eliminateimport('@/pages/' + path)
Written in vite warning β οΈ
-
Plug-in vite – plugin – dynamic – import
npm i -D vite-plugin-dynamic-import Copy the code
-
So this is kind of a tricky one, and there are two things to think about
@
This alias replacement —- vite reported an errorpath
Dynamic path analysis —- vite warning
-
The principle of analytic
impot('@/pages/' + path)
You essentially enumerate all the files under Pages and generate oneswitch
To provide matching
If the directory structure is as follows:
β β β SRC / | β β β pages / | | β β β foo vue | | β β β bar / | | | β β β index. The vue | β β β routes. The tsCopy the code
// src/routes.ts function load(path) { return import('@/pages/' + path) } const routes = [ { name: 'foo'.path: '/foo'.component: () = > load('foo'),}, {name: 'bar'.path: '/bar'.component: () = > load('bar'),},]Copy the code
Will generate:
function load(path) { return __variableDynamicImportRuntime__('@/pages/' + path) } const routes = [ { name: 'foo'.path: '/foo'.component: () = > load('foo'),}, {name: 'bar'.path: '/bar'.component: () = > load('bar'),},]// List all possible paths function __variableDynamicImportRuntime__(path) { switch (path) { case './pages/foo': return import('./pages/foo.vue'); case './pages/foo.vue': return import('./pages/foo.vue'); case './pages/bar': return import('./pages/bar/index.vue'); case './pages/bar/index': return import('./pages/bar/index.vue'); case './pages/bar/index.vue': return import('./pages/bar/index.vue'); }}Copy the code
-
See the dynamic-import-vars link
conversionrequire
δΈΊ import
grammar
-
Plug-in vite plugin — commonjs
npm i -D vite-plugin-commonjs Copy the code
-
The problem is CommonJs to ESModule, NPM found several packages do not implement my function (either do not convert, or inject environment variables error); Simply wrote a simplified version of their own, but also to broaden their technical line (can not eat ready-made, will do their own is not)
-
Technology selection
acorn
Js Abstract Syntax tree (AST) toolacorn-walk
Syntax tree traversal tool
-
The principle of analytic
- Let’s use Acorn to convert the code to
AST
- Use acorn-walk to traverse
AST
Parse out the file that require loads and convert it to import format
If there is code below
const pkg = require('.. /package.json'); const routers = [{ path: '/foo'.component: require('@/pages/foo.vue').default; }]; Copy the code
Will generate:
import pkg from ".. /package.json"; import _MODULE_default___EXPRESSION_object__ from "@/pages/foo.vue"; const routers = [{ path: '/foo'.component: _MODULE_default___EXPRESSION_object__; }]; Copy the code
- Let’s use Acorn to convert the code to
The compatible webpackrequire.contex
grammar
-
Plug-in @ originjs/vite – plugin – the require – context
npm i -D @originjs/vite-plugin-require-context Copy the code
-
Consistent with vite’s built-in import.meta.globEager behavior
support<script>
Write in code blockjsx
grammar
- in
@vue/cli
The configurationbabel.confg.js
You can use it directlyjsx
- in
vite-plugin-vue2
Need to specify<script lang="jsx">
Complete configuration
- Add in the project root directory
vite.config.ts
Note: The following configuration may need to be adjusted to suit your project
import path from 'path'
import { defineConfig } from 'vite'
Mandatory * Vite supports the official vue2 plug-in
import { createVuePlugin } from 'vite-plugin-vue2'
// Mandatory * Read public/index.html
import htmlTemplate from 'vite-plugin-html-template'
// Optional - compatible with CommonJs
import { vitePluginCommonjs } from 'vite-plugin-commonjs'
// Optional - compatible import('@views/' + path)
import { dynamicImport } from 'vite-plugin-dynamic-import'
// Optional - compatible with webpack require.contex
import viteRequireContext from '@originjs/vite-plugin-require-context'
export default defineConfig({
plugins: [
createVuePlugin({
jsx: true,})./** * webpack project require */
vitePluginCommonjs(),
/** * compatible with import('@views/' + path)
*/
dynamicImport(),
/** * require. Context in webpack project */
viteRequireContext(),
/** * Uses the public/index.html template */ by default
htmlTemplate(),
],
resolve: {
alias: [{find: The '@'.replacement: path.join(__dirname, 'src')}, {find: ~ / / * * // ^ ~? = \ /), replacement: path.join(__dirname, 'node_modules')}, {find: / * ~ * // ^ ~? ! / / /), replacement: path.join(__dirname, 'node_modules/')},].// Same as extensions in Webpack
extensions: ['.vue'.'.js'.'.jsx'.'.ts'.'.tsx'.'.json'],},define: {
/ / with webpack DefinePlugin
'process.env': process.env,
}
})
Copy the code
run
-
Add the packge.json scripts command
{ "scripts": { + "vite": "export NODE_ENV=development; vite"}}Copy the code
npm run vite
π Boom shakalaka!!!