Developing a third-party plug-in for Vue with typescript (1)

Time:2021-10-27

Write a Vue specific plug-in based on the micro front-end Qiankun

The purpose of this project is to write a Vue specific plug-in based on Qiankun, a micro front-end framework, to facilitate its use in Vue projects.

At first, I wanted to write in JS. But now we are developing a third-party class library, so we should consider universality. If you write in JS and use the Vue project of typescript, you will encounter the problem of missing the type definition file. Therefore, TS development is adopted. In this way, the generation of declaration files becomes easier.

Project address

https://github.com/Hades-li/qiankun-vue

install

yarn add qiankun-vue
npm install qiankun-vue --save

From Vue cli to handwritten webpack configuration

Vue cli is the official scaffold tool of Vue. It is a fool construction project and is very easy to use. But perhaps it is more suitable for developing a complete set of applications than a small third-party library.

directory structure

Developing a third-party plug-in for Vue with typescript (1)

  • Build: store the webpack configuration file (handwritten later)
  • Dist: final file output directory
  • Example: used to display columns. In fact, this directory is the SRC directory originally generated with Vue cli, but because we want to develop a third-party library, the SRC directory is used to place the library source code, so we changed the directory.
  • SRC: a place to put the source code.
  • Types: typescript type definition file

Use Vue cli official build mode (deprecated)

Vue cli provides an official build librarymethod

vue-cli-service build --target lib --name myLib [entry]

The result of this construction is the same as the official display, and multiple JS library files will be generated at the same time. In fact, we only use one in project reference. In other words, we don’t want to generate a pile of things we don’t want.

Modify vue.config.js build (deprecated)

Give up the official method of Vue cli, and the remaining method is to rewrite the vue.config.js configuration to quickly realize the construction. Here are some important code snippets to explain

if (isProd) {
      config.entry('index').clear().add('./src/index.ts')
      config.output
        . filename ('index. JS') // output file name
        . librarytarget ('umd ') // packaging type
        . Library ('qiankunvue ') // global variable name
        ......
}

In the production environment, the entry file is the entry file under the SRC path.
The output file is set to index.js, the target type is UMD format, and the global variable is qiankunvue

if (!isProd) {
     config.entry('index').clear().add('./example/main.ts')
}

In the development environment, the purpose is not to package and output the source code of SRC, but to run the columns in example. So set the entry file to the main.ts file under example.

//Exclude Vue
config.externals({
    vue: {
      root: 'Vue',
      commonjs: 'vue',
      commonjs2: 'vue',
      amd: 'vue'
    }
})

Because we are developing Vue plug-ins, we need to exclude Vue.

At this time, after executing the yarn run build, only one index.js file will be generated in the dist directory. Of course, since I did not shield the HTML template plug-in, index.html will still be generated.

Finally, I gave up the above two Vue cli construction methods, because I found that the size of the packaged index.js file was as high as 120 + KB. This size is obviously too large. But I can’t find the reason.

Webpack configuration starts

The purpose of this change is to completely independent of Vue CLI and completely customize the development and production environment.
Developing a third-party plug-in for Vue with typescript (1)
Build.js – performs webpack packaging in a functional manner. (temporarily abandoned)
Here are some key code snippets

webpack.config.base.js

Basic configuration, including the configuration required by both production and development environments

module.rules
//Preprocessing. TS files
{
  test: /\.ts$/,
  use: [
    'babel-loader',
    {
      loader: 'ts-loader',
      options: {
        appendTsSuffixTo: [/\.vue$/],
        transpileOnly: true
      }
    }
  ],
  exclude: /node_modules/
},
//Preprocessing. Vue files
{
  test: /\.vue$/,
  loader: 'vue-loader'
},

These two pieces of code are mainly preprocessing. TS files and. Vue files.
Babel loader is optional and is used to convert ES6 code into Es5 for compatible browsers. Today’s modern browsers such as chrome, edge and Firefox have good support for ES6 and even ES7. Without Babel loader, the size of packaged files can be further reduced and the operation efficiency can be higher. However, in the attitude that some people may use IE, add it easily.

//Pretreatment SCSS
    {
      test: /\.s[ac]ss$/,
      use: [
        env.NODE_ENV !== 'production' ? 'vue-style-loader' : MiniCssExtractPlugin.loader,
        'css-loader',
        'sass-loader'
      ]
    },
    //Preprocessing CSS
    {
      test: /\.css$/,
      use: [
        env.NODE_ENV !== 'production' ? 'vue-style-loader' : MiniCssExtractPlugin.loader,
        'css-loader'
      ]
    },

Preprocessing SCSS, and CSS styles. In fact, in the project built by Vue cli, two other precompiled style files, less and styleu, can be supported. However, we now customize the webpack configuration. In line with the principle of matching what we use, we only need to meet our own needs.

//Preprocessing picture
{
  test: /\.(png|jpe?g|gif|webp)(\?.*)?$/,
  loader: 'url-loader',
  options: {
    limit: 4096,
    Esmodule: false, // versions above 5.0 should be added
    fallback: {
      loader: 'file-loader',
      options: {
        name: 'img/[name].[hash:8].[ext]'
      }
    }
  }
}

Preprocessing image, here we will focus on the pit of this configuration item. This configuration is used to resolve picture / file paths and Base64 convert pictures. At first, I used it directlyVue cli reviewA webpack configuration file is produced and copied. Compared with the above code, there is only no esmodule: false parameter. The result of running is that all pictures are not displayed, and the view picture path is like this<img src=[object module]>。 So add esmodule: false and it’s OK.

The above reason is that when Vue loader parses the. Vue file,

<img>

The tag will be compiled into

createElement('img', {
  attrs: {
    SRC: require ('.. / image. PNG') // commonjs syntax import function. Now this is a module request
  }
})

Require is the import function of the commonjs specification. By default, URL loader recognizes the import syntax of ES6, that is, import. Therefore, the final converted code can not display the picture normally. Esmodule: false is to enable the commonjs import method.

Then why does the project built by Vue cli not need to configure this parameter?
Because the URL loader version number adopted by Vue cli still stays at 2. X.x. The latest version has reached 4. X.x. The old version of URL loader did not have this restriction mechanism. The new URL loader is a standard specification that encourages the adoption of ES6 to introduce files. Commonjs is the specification of nodejs.

plugins
plugins: [
      New vueloaderplugin(), // cooperate with Vue loader
      New forktscheckerwebpackplugin(), // run the TS loader type check in an independent thread to speed up the compilation
      new webpack.DefinePlugin({
        'process.env': {
          NODE_ENV: '"' + env.NODE_ENV + '"',
          BASE_URL: '"/"'
        }
      }), // add global variables to the browser code
      New friendlyerrorsplugin(), // friendly error prompt
      New minicssextractplugin(), // CSS extraction
      New casesensitive pathsplugin() // strict path case
    ]

These plug-ins are basically added after Vue cli review. Some can not be added, but it is very helpful for development.

webpack.config.prd.js

Configuration in production environment.

module.exports = merge(baseConf({ NODE_ENV: env }), {
  mode: env,
  entry: './src/index.ts',
  output: {
    path: resolve('dist'),
    filename: 'index.js',
    publicPath: '/',
    chunkFilename: 'js/[name].[contenthash:8].js',
    libraryTarget: 'umd',
    library: 'QiankunVue'
  },
  externals: {
    vue: {
      root: 'Vue',
      commonjs: 'vue',
      commonjs2: 'vue',
      amd: 'vue'
    }
  },
  plugins: [
    //Clean up dist folder
    new CleanWebpackPlugin()
  ]
})

The configuration of production environment is relatively simple. First, throughwebpack-mergeThis plug-in merges the configuration of webpack.config.base.js, adds the configuration items of entry and output, and cleans the dist directory with the cleanwebpackplugin plug-in, which can be packaged with one click.

webpack.config.dev.js

Configuration in development environment.

entry: './example/main.ts',
  output: {
    path: resolve('dist'),
    filename: 'app.js',
    publicPath: '/'
  },
  devServer: {
    contentBase: resolve('dist'),
    port: 8080,
    hot: true,
    Progress: true, // 0-100% progress prompt
    Quiet: true // remove a pile of alarm information
  },
  devtool: 'eval-source-map',

For the development environment, also merge webpack.config.base.js, rewrite the entry to point to example / main.ts.
Configure the development server devserver. Remember to install itwebpack-dev-serverThis bag.

plugins
plugins: [
    New webpack. Hotmodulereplacementplugin(), // supports hot module replacement
    new HtmlWebpackPlugin({
      title: 'qiankun',
      template: resolve('public/index.html'),
      favicon: resolve('public/favicon.ico')
    }), // configure the index.html template
    new CopyWebpackPlugin([
      {
        from: resolve('public'),
        to: resolve('dist'),
        toType: 'dir',
        ignore: ['index.html']
      }
    ]) // copy the plug-in, which is used to copy some static resources that are not involved in packaging to the dist directory
  ]

These are necessary plug-ins in development mode

The above webpack configurations are much less than those provided by Vue cli. For example, we didn’t even compile the loader configuration item for the. JS file because our project only plays ts. The actual TS project built with Vue cli can be developed with JS and ts. But the purpose of pure handwritten webpack is to only meet your own needs.

This issue focuses on webpack configuration, which is also one of the difficulties in this project, which is time-consuming and laborious.

Legacy problem 1 – unable to automatically generate *. D.ts file

Develop a standard JS library. No matter whether you use js or ts, now you have to write TS type declaration files for your library. Famous libraries such as lodash and jQuery didn’t have declaration files in the early days. As a result, if it is used for TS project development, the type detection mechanism cannot be carried out (there was no typescript in the early stage). But now, these libraries have added type declarations.
Type declarations can be written by hand, but they are too cumbersome. It’s best, of course, to generate it automatically.
Officially, it is configured in tsconfig.jsdeclaration: trueCan be generated automatically. But there was no response.
Of course, if you compile directly with the TSC — Declaration command line, you can generate. At present, this is a legacy problem. If a great God knows the solution, forget to give advice.

Recommended Today

Swift advanced (XV) extension

The extension in swift is somewhat similar to the category in OC Extension can beenumeration、structural morphology、class、agreementAdd new features□ you can add methods, calculation attributes, subscripts, (convenient) initializers, nested types, protocols, etc What extensions can’t do:□ original functions cannot be overwritten□ you cannot add storage attributes or add attribute observers to existing attributes□ cannot add parent […]