The cause of

There is a requirement that a single page application (Vue, React) can automatically generate a version output to the target directory (dist) when performing packaging. In this way, when a Bug occurs online, you can know which version to modify and locate the problem.

To solve the process

Manually add version information

Of course, you can manually add some version information in the output directory version. TXT, but every release package needs to be manually added, it is obviously not in line with the style of programmers, repeated things of course need to use code to replace the solution

Write anodejsThe script

  • So the first thing that comes to mind is we could write onenodejsTo invoke thegitRelated commands get the current version information and write toversion.txtIn, the execution time is executenpm run buildAfter.package.jsonModified as follows:
"script:": {
    "build": "script/build.js && node script/version.js"
}
Copy the code
  • The js script is as follows:
// version.js
const execSync = require('child_process').execSync;
const fs = require('fs');

// Get git information
const COMMITHASH_COMMAND = 'rev-parse HEAD';
const VERSION_COMMAND = 'describe --always';
const BRANCH_COMMAND = 'rev-parse --abbrev-ref HEAD';
try {
    const d = new Date(a);const versionStr =`
        Revision: ${execSync(`git ${COMMITHASH_COMMAND}`)}
        Branch: ${execSync(`git ${BRANCH_COMMAND}`)}
        Release: ${execSync(`git ${VERSION_COMMAND}`)}
        X-PackingTime: ${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}${d.getHours()}:${d.getMinutes()}
        `;
    fs.writeFileSync(`dist/version.txt`, versionStr);
} catch (e) {
    throw new Error(e);
}
Copy the code
  • With the above two steps directly executenpm run buildExecution can then be executedWebpackAutomatic execution after packagingversion.jsScript that automatically writes version information todist/version.txtIn, free hands.

Through the analysis of the above two steps, you can already implement a script that automatically generates version information, but there are still some problems:

  • Script execution is inflexible and there is no way to pass in parameters to suit different projects
  • Every project needs to be combinedversion.jsThe file is copied to the specified directory and then added to the command line to be executed using Node
  • Different projects may require separate manual maintenance scripts, which is not conducive to the maintenance of the script. If there is a uniform change, it needs to be modified for each project, and there is still a lot of repetitive work to do

throughWebpackThe plug-in writes version information

The above analysis of our protagonist is clear, my solution is:

  • Write aWebpackThe NPM package of the plugin, which uses the hook function provided by WebPack to get the version information after the build and write it locally
  • Publish to the company’s private repository (it is not high enough to publish to the public NPM 😅)
  • Use NPM to install and configure directly toWebpackthepluginsDifferent parameters can be passed in to suit different projects

Developing an NPM package that can be published to AN NPM or NPM private repository requires some knowledge of the NPM package development and distribution process

Development process (usenpm link) :

  • Under the package and directorynpm linkTo establish a global link to the developed NPM package
  • In the project root directory usednpm line package-namePackage-name is the package name configured in package.json
  • cancelnpm unlink

Release process:

  • Prepare the NPM account. For private servers, set the address of the local NPM repository to the private server address
  • The loginnpm login
  • releasenpm publish
  • usenpm install xxx [options]

Write the Webpack plug-in

The best teacher to learn something new should be the official documentation, through the documentation can quickly write their own need for plug-in functions

  • First, plugins all have an apply method, which has a compiler parameter:
const pluginName = 'RepoRevisionWebpackPlugin';

// Get git information
const COMMITHASH_COMMAND = 'rev-parse HEAD';
const VERSION_COMMAND = 'describe --always';
const BRANCH_COMMAND = 'rev-parse --abbrev-ref HEAD';

class RepoRevisionWebpackPlugin {
  constructor (options = {}) {}
  apply(compiler) {
    // Compiler instances have hooks for each lifecycle of WebPack execution
    // The first argument to the tap method is the humped name of the plug-in, and the callback function can do whatever business logic it wants
    compiler.hooks.run.tap(pluginName, (compilation) = > {
      console.log('Webpack build process begins! ');
    });
    // I'm using the done event to execute my business logic after the build is complete
    compiler.hooks.done.tap(pluginName, () = > {
        console.log('Webpack build process finished! ');
        try {
            const d = new Date(a);const versionStr =`
                Revision: ${execSync(`git ${COMMITHASH_COMMAND}`)}
                Branch: ${execSync(`git ${BRANCH_COMMAND}`)}
                Release: ${execSync(`git ${VERSION_COMMAND}`)}
                X-PackingTime: ${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}${d.getHours()}:${d.getMinutes()}
                `;
            // Compiler instances can get the parameters passed in when the plugin is used
            fs.writeFileSync(`${compiler.options.output.path}/version.txt`, versionStr);
        } catch (e) {
            throw new Error(e); }}}})module.exports = RepoRevisionWebpackPlugin;
Copy the code
  • This is easy to use, as you can create an NPM link through the development process described above, and import and configure it directly into plugins in the WebPack configuration file
const RepoRevisionWebpackPlugin = require('RepoRevisionWebpackPlugin');
module.exports = {
  plugins: [
    new RepoRevisionWebpackPlugin({}),
  ]
}
Copy the code

The webpack plugin can be used to obtain git version information, and can be used to release a crude NPM package for other projects.

Of course, the above function is very simple, only as a hint, there are also a lot of places to improve, such as:

  • Unit testing
  • Do more with compiler and compilation hooks (both of which provide event functions that enable developers to do more, as mentioned below)

One day

  • Need to pay attention toWebpackVersion issues,Webpack4The previous hook function is not the same as the later hook function, and you need to determine whether you need to be compatible with the lower versionWebpack
  • Install the NPM private repository, which can be accessed throughDockerThe way fastThe installationA NPM private server of your own

To move the brick

  • Webpack Plugins
  • Compilation hooks
  • The compiler hooks
  • Use Verdaccio to build a private NPM repository