Modern Library Development Guide Series front-end (B): Using webpack build a library

Foreword

In the foregoing, I said that this series of articles in the audience is a modern front-end system proficient students write business code, so this article Introducing webpack configuration, referred only to build a library-specific configuration, please refer to the rest of the configuration webpack official documents.

Product output

Construction of a library with a general application to build the biggest difference is constructed after the completion of product output .

After the completion of construction of general application will output:

  • A html file
  • Js inlet a chunk, several sub-chunk
  • Several css file
  • A number of other resources, such as images, fonts and other files

Although the output of a lot of resources, but in fact all dependencies, relations have been loaded from html files start to settle down layer by layer, in other words, the html file actually is the entrance to the entire application.

After the completion of construction of a library will output:

  • CommonJS a js file format
  • js file an uncompressed format UMD
  • js file a compressed format UMD
  • May include several css file
  • It may include a number of other resource files

Entrance library are listed above js files; you might wonder how a library will have three entrances documents? Moji, listen to me one by one.

CommonJS

CommonJS is Node.js implementation of a modular specification, mainly including grammar module.exports, require()and so on; and when we use webpack introduced npm package, in fact, Node.js environment, can be seen, this CommonJS entry js file format ( <库名称>.common.js) is introduced npm packages for other applications in Node.js environment of use. Since when referring npm package volume is generally not much thought npm package (application when building their own compression if necessary), and in order to facilitate debugging, so that the file entry is not js compressed.

UMD

UMD is a modular specification hodgepodge, in addition to CommonJS compatible, it also compatible with AMD modular specification, as well as the most traditional global variable mode.

Here a little more about AMD specification, AMD stands Asyncchronous Module Definition , the general application in the browser (this is the biggest difference CommonJS specification), the most famous of AMD loader is RequireJS . At present, because of popular webpack, AMD this modular approach has gradually withdrawn from the market.

Global variable mode it is well understood, is the entrance to the library to mount in a global variable (such as window.xxxthe), anywhere on the page can be readily accessible, are among the most traditional js plugin loader program.

From the above, the inlet UMD js file format, reference may be used for the scene npm packet (uncompressed version, <库名称>.umd.js), it may be used directly in the browser (the compressed version, namely <库名称>.umd.min.js).

How to build libraries of different modular specification

Currently, webpack does not support simultaneous multiple entry js file is generated, it is necessary to build multiple times.

The key webpack configuration is:

  • CommonJS:output.libraryTarget: "commonjs2"
  • UMD:output.libraryTarget: "umd"

For UMD, we also need to set a global variable name, that is output.library: "LibraryName".

In order to bring out the compressed file constructed, the easiest method is to call WebPACK command in the CLI mode parameters, such as webpack --mode=production; this is because when the value of mode is productionwhen, WebPACK automatically enabled UglifyJsPlugin of source compression.

Output version information

I work in a company, the company's reliance on third parties very strict, all rely on the use of third parties in the project must be reviewed in order to use the application and through; and when the application is accurate to the specific version, does not apply the software version is also not and will not be used. Some third-party depend on whether the contents of the file, or in the file name, did not reflect the publication of this number, which we identify such third party to rely create an obstacle, which is the need to learn a lesson we develop own library of.

When building the library, we can use the repository webpack output directly to the contents of the file in, with this "identity", the user can also use extra peace of mind.

O library version information is to use webpack.BannerPlugin, easiest to use are as follows:

const pgk = require('./package.json');
const banner = `
${pkg.name}
${pkg.description}\n
@version v${pkg.version}
@homepage ${pkg.homepage}
@repository ${pkg.repository.url}\n
(c) 2019 Array-Huang
Released under the MIT License.
hash: [hash]
`;

/* webpack 配置 */
{
    // ...其它配置
    plugins: [
        // ...其它 plugin 配置
        new webpack.BannerPlugin(banner);
    ]
}

The final effect is generated out:

/*!
 * 
 * vue-directive-window
 * Vue.js directive that enhance your Modal Window, support drag, resize and maximize.
 * 
 * @version v0.7.5
 * @homepage https://github.com/Array-Huang/vue-directive-window
 * @repository git+https://github.com/Array-Huang/vue-directive-window.git
 * 
 * (c) 2019 Array-Huang
 * Released under the MIT License.
 * hash: dc6c11a1e50821f4444a
 * 
 */

source map

If the user base directly by loading your library browser to use, then provide a source map file is very necessary; this is because your library is built after webpack, even after compression, and source code have been very different, the user will be difficult to debug in the browser; but if you can attach a source map for his library, the browser developer tools will be called to help resolve the source map, the user experience will be closer to debug debugging source code library.

Corresponding webpack configured to:

// webpack 配置
{
    // ...其它配置
    devtool: 'cheap-module-source-map'
}

webpack support multiple types of source map, in different types of source map generation speed, support functions are different manifestations (such as babel), debugging positional deviation and other issues and I am only recommend:

  • Development Environment: Cheap-Module-eval-Source-the Map
  • Production environment: Cheap-Module-Source-the Map

For other types of source map, please see the section webpack devtool official documents.

Exclusion of third party reliance

Unlike general application, in the development of the library, we should try to avoid third-party libraries (except build tool chain used in the process), because the size of these third-party libraries will let us write the library soared; likely this happens: we own a small function to write only a few hundred lines of code logic, constructed out of the library there are hundreds of k, that such a library is not much significance.

But we do it is difficult to avoid the use of third-party libraries, that which we supposed to do?

// webpack 配置
{
    // ...其它配置
    externals: {
        lodash: {
            commonjs: 'lodash',
            commonjs2: 'lodash',
            amd: 'lodash',
            root: '_'
        }
    }
}

After using the above configuration, we build out of the library will not be included in the configuration specified third-party libraries (for example lodash), and one by one the following breakdown:

  • commonjsAnd commonjs2entries are specified user when the current library in node.js environment, CommonJS way to load the name lodashof npm package.
  • amdEntry indicates when loading the library run in a browser, the library will attempt to AMD 's way to load named lodashAMD modules.
  • rootEntry indicates when loading the library run in a browser, the library will attempt to take global variables window._(by <script>tag loading lodash.jstime, lodash will inject themselves into the global variable window._in).

And general application configuration is not the same externals

In a typical application, you might see such externals configuration:

// webpack 配置
{
    // ...其它配置
    externals: {
        lodash: '_'
    }
}

Such externals configuration means: no matter what the environment, should take _the global variable; if the current application is in general use and has been determined <script>to load the specified third-party libraries (such as jQuery , Vue core library, which is very often this way to load), of course, could have such direct use; but we, as authors library should provide a more relaxed and more flexible use.

Webpack complete configuration examples

Due to the modular construction of different specifications require different webpack library configuration (in fact, only slightly different) to build multiple times, so this only for building UMD format and compressed the scene to show the easiest webpack configuration example; if want to know how to more efficiently splicing webpack configuration, see the micro-schema-validator project webpack profile:

// webpack.config.js
const webpack = require('webpack');
const pkg = require('./package.json'); // 把 package.json 作为信息源
const banner = `
${pkg.name}
${pkg.description}\n
@version v${pkg.version}
@homepage ${pkg.homepage}
@repository ${pkg.repository.url}\n
(c) 2019 Array-Huang
Released under the MIT License.
hash: [hash]
`;

module.exports = {
  entry: `${__dirname}/index.js`,
  devtool: 'cheap-module-source-map',
  output: {
    path: `${__dirname}/dist`, // 定义输出的目录
    filename: 'micro-schema-validator.min.js', // 定义输出文件名
    library: 'MicroSchemaValidator', // 定义暴露到浏览器环境的全局变量名称
    libraryTarget: 'umd', // 指定遵循的模块化规范
  },
  /* 排除第三方依赖 */
  externals: {
    lodash: {
      commonjs: 'lodash',
      commonjs2: 'lodash',
      amd: 'lodash',
      root: '_'
    }
  },
  module: {
    rules: [
      {
        test: /(\.jsx|\.js)$/,
        loader: 'babel-loader',
        exclude: /(node_modules|bower_components)/
      },
      {
        test: /(\.jsx|\.js)$/,
        loader: 'eslint-loader',
        exclude: /(node_modules|bower_components)/
      }
    ]
  },
  plugins: [
    new webpack.BannerPlugin(banner) // 输出项目信息
  ]
};

Vue-cli use custom configuration and management webpack

For ecological Vue libraries, such as assembly Vue, Vue custom command or the like, may be used vue-cli (especially 3.0 version herein vue-cli) be tailored to your needs webpack configuration can be customized content comprises:

  • Whether enabled Babel
  • Whether access TypeScript grammar
  • Whether to support the PWA
  • Whether Vue-Router and Vuex
  • Whether CSS preprocessor, and optionally a specific CSS preprocessor comprising Sass / Less / Stylus
  • Whether ESLint and Prettier
  • Testing whether the access unit and test end to end (the E2E)

After custom finishes, vue-cli will generate a seed project, which executable (including local development and build the package production environments) but no actual content (actual content does not have to write to you Well ha ha). Compared with the general scaffolding tool, vue-cli In addition to generating webpack configuration, will also continue to manage and maintain, such as:

  • Providing access to a unified custom configuration; in the past, were we to achieve custom configuration, often generated directly out of the scaffolding tool webpack configuration directly modify, this will lead to a revision is very scattered, making it difficult for custom webpack configuration in other projects multiplexing; while the use of vue-cli, all of webpack configuration changes are centrally managed point up the need to reuse it, direct migration of these custom configuration files (vue.config.js) to other projects can be.
  • Providing continuous update mechanism webpack configuration; if now before I have an open source library for my own purposes, wanton modified on the source code, so when I need to upgrade the open source library may screenwriters, because it would make modifications are overwritten; Similarly available, vue-cli due to the unified entrance custom configuration, and is run every time the project (the project is run by executing vue-cli command rather than webpack) when dynamic rendering webpack configurable, so webpack project configuration can be upgraded with vue-cli constantly upgraded.
  • It provides a mechanism for continually updated webpack tool chain; we all know, webpack tool chain contains a large number of third party open source libraries, such as Babel, ESLint, these open source libraries are also among the constantly updated, in the process, will inevitably continue to produce Breaking Change, fortunately vue-cli upgrade by itself - constantly revised webpack configuration to achieve the purpose of adapting the latest third-party open source libraries, and our project can also be a minimum price (upgrade vue-cli itself) to get webpack constantly updated tool chain.

vue-cli custom configuration example

Taken VUE-Directive-window vue.config.js project file:

const webpack = require('webpack');
const pkg = require('./package.json');

const banner = `
${pkg.name}
${pkg.description}\n
@version v${pkg.version}
@homepage ${pkg.homepage}
@repository ${pkg.repository.url}\n
(c) 2019 Array-Huang
Released under the MIT License.
hash: [hash]
`;

module.exports = {
  chainWebpack: config => {
    config.output.libraryExport('default');
    config.plugin('banner').use(webpack.BannerPlugin, [
      {
        banner,
        entryOnly: true,
      },
    ]);
  },
};

Appears to be even simpler than the above is not the most basic webpack configuration? When the project structure gradually enriched, this gap will continue to widen.

I want to read more technical articles? I go to the GitHub blog Array-Huang / blog to, if there is help for you, please take a Star & Watch Bo Ha (〃 ^ ω ^)

Guess you like

Origin blog.51cto.com/14632674/2457295