I remember Vite2 will be launched around the Spring Festival of 2021. I only knew about it when I saw an article on wechat. At that time in exclamation: I am celebrating, but others are promoting technology! So when I went to work after the New Year, I grasped the fish and studied it before all the projects came back from the festive atmosphere. The purpose of fishing… Bah! The research aims are as follows:

  1. Before have taken multiple pages based on Vue – Cli scaffolding, and also used in practical projects, the hot update speed I will brush weibo enough, in order to speed up the hot update at that time, are not involved in the scaffolding in advance or relatively stable module entry to filter out the first, only keep the current development module to use, you can imagine when there is a much slower.
  2. React scaffolding is too heavy to handle, umiJS is too heavy to like, create-React-app needs to install extra exposed interface package if it needs to be customized, it feels like the official blood is polluted. While the others are messy, it was interesting to see that Vite could be used to build scaffolding based on the React stack.

After a little experimentation, I put it aside.

Type YARN or NPM install and I can do this scaffolding

Then I saw an article whose title I forgot, but only the general content:

The author suggested Vue to the leader, who replied, “You want to eat shit?” .

This article took me to try react + antD + Vite, then I picked up Vite to rebuild my previous vuE-CLI multi-page, and tried to add tailwindCSS.

Based on these tentative efforts, vite + vue3 + tailwindcss was put into practice in the recent hybrid development of H5. The results… Ok, pit stepped over, I finally understand some surface, the following is the actual combat summary.

Vite and TailwindCSS I’m going to assume you’ve already installed them.

Tailwindcss

Tailwindcss is based on the idea of atomization to minimize style repetition. Originally, Tailwindcss was developed to maximize class name based declaration block duplication. Now, Tailwindcss is based on single sentence declaration non-repetition.

Development experience:

  • You don’t have to think about the class name, right
  • A lot less styling
  • It takes extra mental capacity to remember the TW class names (improved with VScode)
  • There are so many classes in HTML that HTML as a whole is crowded

Problems encountered:

  • What if there is no corresponding value for length and width in tailwindcss?
  • Px in the design, how to gracefully convert to REM or VW and VH?
  • How do colors, fonts, etc., expand?
  • How do I address the congested feel of classes in HTML?

Solution:

What if there is no corresponding value for attributes such as length and width in tailwindcss?

Tailwindcss 2.1 has added a braced feature that allows users to customize values, making it much more flexible with writing styles.

/* If the height is 22px, it can be written as z-index, as can various color attributes */
.example {
  @apply h-[22px];
}
.example {
  @apply z-[-1];
}
Copy the code
Px in the design, how to gracefully convert to REM or VW and VH?

The adaptation of mobile terminal is a point to be concerned about in the development process. In addition to media query breakpoints, the adaptation method is basically REM + HTML font dynamic setting and vw(VH) processing.

Tailwindcss is processed in REM by default, but in the design, it is displayed in PX, so it is not possible for every value to be processed in REM by manual calculation. For those of you who have used SASS or LESS, you should think of function in preprocessor.

Although tailwindCSS can be combined with SASS or less, there is a sense that tailwindCSS itself is based on PostCSS and can be handled with two extensions to PostCSS: Postcss – px – to – viewport and postcss – pxtorem

'postcss-px-to-viewport': {
   unitToConvert: 'px'.// The unit to convert
   viewportWidth: 375.// Width of UI design draft
   unitPrecision: 6.// The precision of the conversion, i.e. the number of decimal places
   propList: ['width, height'].// Specify the unit of the CSS property to be converted. * indicates that all CSS properties are converted
   viewportUnit: 'vw'.// Specify the window unit to convert to, default vw
   fontViewportUnit: 'vw'.// Specify the window unit to convert the font to, default vw
   selectorBlackList: ['wrap'].// Specify the class name that is not converted to window units,
   minPixelValue: 4.// The default value is 1, and the conversion is not performed if the value is less than or equal to 4px
   mediaQuery: true.// Whether the media query is also converted in the CSS code, the default is false
   replace: true.// Whether to replace the attribute value directly after conversion
   exclude: [/node_modules/].// Sets the file to be ignored and the re to match the directory name
   landscape: false // Whether to handle landscape
 },
'postcss-pxtorem': {
   rootValue: 16.unitPrecision: 6.propList: ['font'.'font-size'.'line-height'.'letter-spacing'].selectorBlackList: [].replace: true.mediaQuery: true.minPixelValue: 4.exclude: /node_modules/i
 }
Copy the code

On my side, REM is mainly used for font, while VW is used for width, height, padding, margin and border. In addition, media query breakpoint processing is fully satisfied with the adaptive of mobile terminal.

How do colors, fonts, etc., expand?

The tailwindcss has its own instructions. If you want to overwrite it, write it directly under theme and if you want to extend it, write it directly under theme.extend. Looking directly at the code, notice the following two fontFamily locations: Sans is the default for overwriting tailwindCSS and bebasNeue is the extended font (also don’t forget to introduce the font file in the main entrance)

theme: {
  fontFamily: {
    sans: ['PingFang-SC-Bold'.'PingFang-SC'.'Microsoft YaHei'.'Microsoft Jhenghei'.'sans-serif']},extend: {
    fontFamily: {
      bebasNeue: ['BebasNeue Bold']},colors: {
      'custom-blue': '#0088FF'.'custom-black': '# 333333'.'custom-gray1': '# 666666'.'custom-gray2': '# 999999'.'custom-gray3': '#B2B2B2'
    },
    screens: {
      '2xsm': '250px'.xsm: '320px'}}}Copy the code
How do I address the congested feel of classes in HTML?

In development you might see something like this:

 <span class="text-[30px] leading-[37px] text-white align-middle ml-[12px] mr-[4px] font-bebasNeue"></span>
Copy the code

Especially in the case of design draft modification, some class names may be written in the process of adjusting the style, which may be repeated or overwritten due to visual congestion. Here’s how I dealt with it:

  • For longer classes, such as more than 5 classes, create a custom class and use that class to apply the name of the tailWindCSS class you want to write.
  • (hover, media-query) (hover, media-query) (hover, media-query)
<span class="custom"></span>
<style lang="postcss">
.custom {
 @apply text-[30px] leading-[37px] text-white align-middle ml-[12px] mr-[4px] font-bebasNeue;
 @apply md:text-[40px] md:leading-[50px];
 @apply hover:text-red;
}
</style>
Copy the code

For simple projects this can be done, but for more complex projects (if the design is a componentized standard design) I suggest simply adding a layer of global custom classes (for computer related problems, add another layer), each class of apply TailwindCSS. Another way to think about it is to write your own UI framework, and then replace the declaration block for each class in the framework with the class name of TailwindCSS.

Vite

Problems encountered

  • How to unpack like Webpack?
  • How to gracefully add environment variables?
  • How to replace local static resources with CDN(OSS) resources when packaging?
  • How to set up an online environment with secondary directories?

Solution:

How to unpack like Webpack?

For this intuitive experience, the Rollup configuration is much cleaner than WebPack

// Rollup unpack configuration
 build: {
   rollupOptions: {
     output: {
       manualChunks(id) {
         if (id.includes('html2canvas')) {
           return 'html2canvas'
         } else if (id.includes('AMapLoader')) {
           return 'AMapLoader'
         } else if (id.includes('echarts')) {
            return 'echarts'
         } else if (id.includes('node_modules')) {
            return 'vendor'
         }
       }
     }
   }
}
Copy the code
How to gracefully add environment variables?

For those of you who are familiar with vue-CLI, you might say, “Why not write process.env.your_variable in viet.config.js?”

Patterns and environment variable | Vue CLI

However, if the front-end page wants to use these variables, it cannot be accessed through Process because the front-end module is based on the ESModule specification and Process is based on the commonJS specification. BTW, process can be accessed in vite.config.js and postcss.config.js.

Why is that? Vite dependency builds

CommonJS and UMD compatibility: During development, Vite’s development server treats all code as native ES modules. Therefore, Vite must first convert dependencies published as CommonJS or UMD to ESM

Js and postcss.config.js should be processed before “dependent pre-build”, while still in the NodeJS environment, so you have access to Process. So how do you deal with it?

It’s okay it’s okay. It’s all in the file. Env Variables and Modes | Vite import.meta – JavaScript | MDN

Well, that’s not a problem. Import. Meta +. Env, with a little configuration, can solve the problem of using environment variables in pages (remember to prefix variables with VITE_). But what if I still want to use variables in viet.config.js? Should I just write process? It works, but it’s not elegant, because you’re already using.env, so instead of scattering variables across your project files, write them in.env. What? Env variables are not read in viet.config.js! How to solve?

Fortunately, fortunately, Google found it, no need to smash the computer.

Env variables not accessible in vite.config.js · Issue #1930 · vitejs/vite

Grandpa said it wouldn’t work because it’s a

It’s a chicken-and-egg problem

Graph TD viet.config. js --> merge config --> get. Env variables
  1. Viet.config. js can configure the project root path,.env in the project root path
  2. Env variables can only be read according to the configured root path after merging options of vite. Config. js
  3. How does viet.config. js make it spit out variables to you before merge Options?

I get it! I get it!

My grandfather closes the door here, but he opens a window there.

  • mode: Indicates the current configuration environmentdevelopment or production
  • envDir: .envFile Directory
  • prefix: This I have not used, combined with vite pair.envThe description of the variable should be a prefix, because forVITE_Prefixes can be exposed to the front-end page, while others are only accessible during the build.

Now that the environment variable problem is gracefully solved, go to code!

// vite.config.js
 const { VITE_OSS_URL, VITE_API_PREFIX, VITE_API_DEV_TARGET } = loadEnv(mode, process.cwd())
Copy the code
How to replace local static resources with CDN(OSS) resources when packaging?

In this project, I mainly used to replace pictures. What I want to achieve is this:

  • I didn’t make any changes during the development process, and of course I didn’t put the images in the static directory (/public), because when I put the images in the static directory, I won’t deal with the resources in the static directory, in case I need to do a unified processing for the images later, so I still introduced the images as usual.

Such as:

<! -- In template -->
<img src="@/assets/images/xxx.png" />
Copy the code
/* In styles */
.example {
  background:url(@/assets/images/xxx.png);
}
Copy the code
// how to import js
import exampleImg from '@/assets/images/xxx.png'
Copy the code
  • When packaging, replace directly without making any changes to the development code, ensuring that no additional configuration is recorded at deployment time, reducing the mental burden.

Towards these two goals, I began to explore slowly. Based on my previous understanding of VUe-CLI configuration, I first checked the configuration related to Assets of Vite and found clues indeed:

AssetsDir Specifies the path to generate static resources (as opposed to build.outdir)

However, this also affects all CSS and JS. No. After a few attempts, I found smartAsset, and after a few more attempts, I finally replaced some of the images with links on OSS. The configuration is as follows

// vite.config.js
build: {
  rollupOptions: {
   plugins: [
     smartAsset({
       extensions: ['.png'.'.jpg'].url: 'copy'.publicPath: VITE_OSS_URL
     })
   ]
  }
}
Copy the code

sormy/rollup-plugin-smart-asset

Why partial? Because this can only handle images in one of two ways:

  1. Import in the form of pictures (for third-party plug-ins to introduce custom images in the project, such as gold site map marker, the third party can not recognize your alias identity, such as imageUrl: ‘@ / assets/images/location. The PNG’)
  2. The image in the IMG tag

How do I do that in background? Backgroundg is related to tailwindCSS, and tailwindCSS is related to postCSS, so you can only look up postCSs-related plugins, and this is also a couple of times to find postCSs-URL.

postcss/postcss-url

The configuration of smartAsset is similar to that of smartAsset.

In other words, under the copy type, the return function of the customized URL can achieve the effect of CDN

I wrote the configuration in the CSS in viet.config.js

 css:{
   postcss: {plugins: []}}Copy the code

I can’t identify tailwind CSS (@tailwind). Look at the Vite documentation first

Postcss Inline postCSS configuration (in the same format as postcss.config.js), or a custom postCSS configuration path (based on the project root by default). The path search is implemented using postCSs-load-config. Note: If this inline configuration is provided, Vite will not search for other PostCSS configuration sources.

The original configuration in viet.config. js will ignore postcss.config.js, while the configuration of tailwindcss is in postcss.config.js. To keep the file clean, we moved the configuration to postcss.config.js as follows:

require('postcss-url') ({filter: '**/assets/images/*.png'.url(assets, dir, options, decl, warn, result) {
    const pathStrArray = assets.pathname.split('/')
    const fileName = pathStrArray[pathStrArray.length - 1]
    // Ensure that local resources continue to be used in the development environment, using CDN online
    return ctx.env === 'production' ? `${VITE_OSS_URL}${fileName}` : assets.url
  },
  maxSize: 10.// maximum file size to inline (in kilobytes)
  fallback: 'copy' // fallback method to use if max size is exceeded
})
Copy the code

How to set up an online environment with secondary directories?

First of all, why to set the secondary directory, because they are some partial H5 active pages, the number of pages is small, online use HTTPS, HTTPS certificate application separately is too troublesome, so use secondary directory to distinguish different sites. This one is relatively simple, just pay attention to two points: add the root path when createRoute

const router = createRouter({
 history: createWebHistory(import.meta.env.BASE_URL),
 routes: []})Copy the code

The BASE_URL can be configured in viet.config.js, but it will also affect the development environment

{
  base : 'yourbaseurl'
}
Copy the code

Yarn Build –base=/ yourBase/yarn Build –base=/yourbase /

  1. Add to the nginx reverse proxy
  • The local Server Proxy may be'/yourprefix/api/xxxx/'
  • Online nginx '^~/baseurl/yourprefix/api/xxxx/'

So far each pit finally filled up, if you see my solution has a problem or a better way to welcome everyone to leave a message!