Inspired by an article on nuggets, I’m going to use VUE to practice writing a small interface, similar to bookmark management.

I designed the interface very simply, creating a floating toolbar in the upper right corner. The idea is to create a new control, inside with V-for loading box, box put font icon.

Start construction and create a new index.less, which is responsible for the global style of the project. Then download the font icon iconfont. There are two ways to refer to font ICONS:

The first is to import the CSS directly from main.js and then pull it out of the package.

The second is to copy iconfont as a static resource package to the specified location, and then reference in HTML.

The first method is chosen: reference in main.js

    import "./assets/iconfont/iconfont.css"
Copy the code

To make it easier to copy a section of the WebPack configuration from a previous project

css: {
    extracttrue.// Whether to use CSS ExtractTextPlugin
    sourceMapfalse.// Enable CSS source maps?
    modulesfalse.loaderOptions: {
      less: {
        javascriptEnabledtrue / / less configuration}}}Copy the code

Let’s compile it and see a warning line in the terminal

WARN  "css.modules" option in vue.config.js is deprecated now, please use "css.requireModuleExtension" instead.
Copy the code

The idea is to replace modules with the new attribute requireModuleExtension. Encountered this warning before, and ignored it and replaced it. Set requireModuleExtension to false. The nightmare began.

After repackaging, the font icon is not displayed and the Woff file is not loaded

<div class="item">
    <i class='iconfont sk-tubiao_qingchu'></i>
</div>
Copy the code

Look at the CSS file and find that CSS has become this ghostly look

.iconfont_iconfont_3MHMU {
  font-family: "iconfont" ! important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
 
.iconfont_sk-tubiao_qingchu_1wtxn:before {
  content: "\e85e";
}
Copy the code

There’s a prefix and a suffix. Try changing iconfont to iconfont_iconfont_3MHMU and SK-tubiao_qingchu to iconfont_sk-tubiao_qingchu_1wtxn. It’s working.

I haven’t seen this format before, but my guess is that there is a problem with CSS compilation. I can speculate on a few sources from my meager knowledge.

  1. The CSS is referenced incorrectly
  2. CSS configuration issues (CSS obfuscation, CSS compression, CSS prefixes, suffixes, etc.)
  • Let’s start with the first theory
import "./assets/iconfont/iconfont.css"
Copy the code

Nothing wrong with that. The alternative loading method is referenced in app.vue

// app.vue
<style>
    @import "./assets/iconfont/iconfont.css";
</style>
Copy the code

Compiling is normal. Exclude reference problems and scope effects.

  • Look at the second theory

Search the difference between prefixes and suffixes after compiling CSS. Use postCSs-loader to add prefixes for different browsers, not to change the class name. So rule that out.

CSS compression: I set the NPM command for the development environment, did not change the CONFIGURATION of vue CLI, will not use compression, skip for the moment.

"serve""vue-cli-service serve --mode development"
Copy the code

Then there is CSS confusion: the mini-CSs-extract-plugin is generally used. View Parameter Description No parameter related to adding a prefix is found. Ruled out.


None of these guesses came up, so I had to change my mind and try to understand the default Vue CLI configuration to see if I could find any clues from the default configuration properties.

The vue CLI configuration file is stored in node_modules/@vue/cli-service/lib/config. Configuration files generally include:

  • Base.js: the default public configuration
  • Prod. js: configuration in the production environment
  • App.js: Target configuration for app
  • Css. js: styles related to CSS, LESS, and SCSS
  • Dev.js: development environment configuration

After a quick scan of the css.js file, I noticed something familiar in the code

 if (isCssModule) {
      cssLoaderOptions.modules = {
            localIdentName'[name]_[local]_[hash:base64:5]'. cssLoaderOptions.modules } }Copy the code

Combining the. Iconfont_iconfont_3MHMU type, we can infer that 3MHMU is a hash value. Tried to change the hash bit [hash:base64:8], recompile the CSS suffix found changed. At this point, you can pretty much identify the problem.

Find the location defined by the isCssModule and trace to it

  // rules for normal CSS imports
  const normalRule = baseRule.oneOf('normal') applyLoaders(normalRule, ! requireModuleExtension)RequireModuleExtension is the value of isCssModule
Copy the code

RequireModuleExtension is defined in the entry function

let { requireModuleExtension } = rootOptions.css || {}
    if (typeof requireModuleExtension === 'undefined') {
          if (loaderOptions.css && loaderOptions.css.modules) {
              throw new Error('`css.requireModuleExtension` is required when custom css modules options provided')
          }
      requireModuleExtension = true
}
 
/ / requireModuleExtension according to CSS. RequireModuleExtension assignment, no it is true.
Copy the code

The problem is the requireModuleExtension parameter. RequireModuleExtension is the opposite of modules value after searching. RequireModuleExtension is set to true to resolve the problem. This parameter is used to parse CSS Modules, and is handled regularly at compile time to resolve style name conflicts.

At the moment I feel ashamed, because I have searched this parameter problem before and forgot it.

A careless cause of the problem is really shouldn’t, especially for the warning. By the way, I summarize the ideas of finding solutions through problems this time, and also provide a conclusion for other problems encountered in the future.