Webpack Front-end Components (3)

This is the 9th day of my participation in Gwen Challenge

Review the

Looking back in the previous two articles, we built a component debug page from an existing Webpack-template step by step, and when the component debug worked, we packaged the component for other users to use.

For those of you who haven’t read part 1 and 2, please read: How to Use WebPack to Pack front-end components.

Use WebPack to pack front-end components (2)

Packaging components

Run the NPM run build command to package the project

When we open the drag.html editor, we find that drag.js has already been introduced in the HTML. In fact, it has already introduced better-draggable-ball. When we open the browser, we find that the dragball can be displayed normally.

When we re-create the HTML file and introduce the better-draggable-ball, we will find the same way as in the original TS:

Drag is not defined

Can we only introduce Drag with configuration items already configured?

The powerful WebPack also gives us the output.library option, which allows you to export your project as a library when webPack is packaged

Configure the document address for the WebPack Library option

We modified the webpack.config.ts configuration file to export the better-Draggable – Ball from our project as a library

In the web

entry: {
    'better-draggable-ball': './src/components/better-draggable-ball/index.ts'
  },
Copy the code

Add the Library property to the Output property.

output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'.clean: true.library:'betterDraggableBall',},Copy the code

Remove the HtmlWebpackPlugin from the plugins attribute because we don’t need to export the HTML file anymore, we just need to export the JS file for its users to reference.

  plugins: [
    new ESLintPlugin({
      extensions: ['js'.'ts'].exclude: '/node_modules/',})],Copy the code

Attach the complete webpack.config.ts configuration file code:

import * as path from 'path';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import ESLintPlugin from 'eslint-webpack-plugin';
import * as webpack from 'webpack';

const config: webpack.Configuration = {
  mode: 'production'.entry: {
    'better-draggable-ball': './src/components/better-draggable-ball/index.ts'./ / better - draggable - ball plug-in
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'.clean: true.library: 'betterDraggableBall'
  },
  resolve: {
    extensions: ['.tsx'.'.ts'.'.js'],},module: {
    rules: [{test: /\.s[ac]ss$/i,
        use: [
          // Generate JS strings as style nodes
          'style-loader'.// Convert CSS to CommonJS modules
          'css-loader'.// Compile Sass to CSS
          'sass-loader',]}, {test: /\.css$/i,
        use: ['style-loader'.'css-loader'],}, {test: /\.(png|svg|jpg|jpeg|gif)$/i.type: 'asset/resource'}, {test: /\.(woff|woff2|eot|ttf|otf)$/i.type: 'asset/resource'}, {test: /\.tsx? $/,
        use: 'ts-loader'.exclude: /node_modules/,}]},plugins: [
    new ESLintPlugin({
      extensions: ['js'.'ts'].exclude: '/node_modules/',})]};export default config;
Copy the code

Now let’s wrap it up again and you can see that the only output in the dist folder is the better-Draggable – Ball file.

Next, we’ll create a test. HTML file in the dist folder, import it with the script tag, and use console.log to print betterDraggableBall to see what’s inside.

Obviously, it is an Object, and there is only one default function in it. Let’s try printing it.

It’s a function. Let’s see, eh? Isn’t that our Drag?

Let’s see if we can try something new.

!!!!!!!!! Note: the location of the packed library is in. Default!!

<script src=".. /dist/better-draggable-ball.js"></script>
<script>
  window.onload = () = > {
    let DragDom = document.getElementById('drag')
    Drag = new betterDraggableBall.default(DragDom)
    console.log(Drag);
  }

</script>
Copy the code

Configure library in webpack.config.ts with the data in default as the default export object, the type attribute as the library exposure, and then pack it up

library: {
      name: 'betterDraggableBall'.type: 'umd'.export: 'default',},Copy the code

Print the betterDraggableBall object. This time, we can see that the default property is not there. Instead, we put the contents of default into the betterDraggableBall object root. It is now possible to create a betterDraggableBall class

We are now only at the point where we can import components via script tags

More import methods are supported

  • set a small goal
    • The files we need to output are (the compressed and uncompressed versions respectively) :
      • aCommonJSThe format ofjsfile
      • aUMDThe format ofjsfile
      • ESMThe format ofjsfile

Here’s a quick look at the formats

CommonJS

CommonJS is the specification for server-side modules, which Is adopted by Node.js. The main syntax is: for example, the require method is used to load modules, and the export method is used to export modules. The CommonJS loading module is synchronous, so the following operations can be performed only after the loading is completed.

AMD

AMD full name Asyncchronous Module Definition, generally applied in the browser (this is the biggest difference with CommonJS specification), the most famous AMD loader is RequireJS. At present due to the popularity of Webpack, AMD this modular scheme has gradually withdrawn from the market.

UMD

UMD is a mashup of AMD and CommonJS, and the most traditional global variable schema. The global variable mode is to mount the entry of the library on a global variable (window.xxx), which can be accessed at any position on the page at any time. It belongs to the most traditional JS plug-in loading scheme, and its emergence is also to solve the problem of cross-platform. UMD determines whether any module (exports) that supports Node.js exists and uses node.js module mode if it does. Check whether AMD is supported (define exists). If AMD exists, load modules in AMD mode.

ESM

Esm is es6 module, which is commonly used in CommonJS and other amD-based module systems before. The key words of ES Modules are import and export, which is also the most popular import mode at present.

We need to modify the configuration file of Webpack. Before, we used a separate configuration method for packaging projects, but now we need to export multiple types of files. At this time, WebPack provides us with a way to export multiple configuration methods (supported by WebPack 3.1.0). Modify webpack.config.ts as follows:

import * as path from 'path';
import { Configuration as webpackConfiguration } from 'webpack';
import ESLintPlugin from 'eslint-webpack-plugin';

const outputConfig: webpackConfiguration[] = [
  {
    output: {
      path: path.resolve(__dirname, 'dist/commonjs'),
      filename: '[name].js'.clean: true.library: {
        name: 'betterDraggableBall'.type: 'commonjs'.export: 'default',},},}, {output: {
      path: path.resolve(__dirname, 'dist/umd'),
      filename: '[name].js'.clean: true.library: {
        name: 'betterDraggableBall'.type: 'umd'.export: 'default',},},}, {output: {
      path: path.resolve(__dirname, 'dist/module'),
      filename: '[name].js'.clean: true.module: true.library: {
        type: 'module',}},experiments: {
      outputModule: true,}},];const baseConfig: webpackConfiguration = {
  mode: 'development'.entry: {
    'better-draggable-ball': './src/components/better-draggable-ball/index.ts'./ / better - draggable - ball plug-in
  },
  module: {
    rules: [{test: /\.tsx? $/,
        use: 'ts-loader'.exclude: /node_modules/}, {test: /\.s[ac]ss$/i,
        use: [
          // Generate JS strings as style nodes
          'style-loader'.// Convert CSS to CommonJS modules
          'css-loader'.// Compile Sass to CSS
          'sass-loader',]}, {test: /\.css$/i,
        use: ['style-loader'.'css-loader'],}, {test: /\.(png|svg|jpg|jpeg|gif)$/i.type: 'asset/resource'}, {test: /\.(woff|woff2|eot|ttf|otf)$/i.type: 'asset/resource',}]},resolve: {
    extensions: ['.tsx'.'.ts'.'.js'],},plugins: [
    new ESLintPlugin({
      extensions: ['js'.'ts'].exclude: '/node_modules/',})]};const config:webpackConfiguration[]|[] = [];
for (let i: number = 0; i < outputConfig.length; i += 1) {
  config[i] = Object.assign(outputConfig[i], baseConfig);
}

export default config;
Copy the code

BaseConfig is used to store the basic configuration of webpackConfig, and outputConfig is used to store three export methods: CommonJS, UMD, Module, Finally, I used a loop and object merge method to generate a new webpackConfig module by combining the base configuration object with different output properties.

// Merge statements
const config:webpackConfiguration[]|[] = [];
for (let i: number = 0; i < outputConfig.length; i += 1) {
  config[i] = Object.assign(outputConfig[i], baseConfig);
}
Copy the code

Let’s package it and see if we can generate a file with multiple import methods:

Nice! Next we create a normal HTML file and try it out using script tag references (UMD).

<script src="./dist/umd/better-draggable-ball.js"></script>
<script>
  console.log(betterDraggableBall);
</script>
Copy the code

Next, try the ESM version, where I create a new Vue Vite project and introduce it into the components in the project.

  // Ignore some code and list only the main code
  import Drag from './better-draggable-ball'
 
  setup: () = > {
    const DragDom=ref<HTMLElement|null> (null)
    // Drag the component to initialize
    onMounted(() = >{
      new Drag(DragDom.value, {
        defaultPosition: { x: 10.y: 10 },
        autoAdsorbent: true}); })return{
      DragDom
    }
  }
Copy the code

Compression link

Why compress

Generally, open source plug-ins and library code are available in two versions:

  1. A readable version, typically intended for developers
  2. A compressed version that is typically provided for use in production environments

Benefits of a compressed version:

  1. Reduced file size
  2. Reduces bandwidth usage for network transmission
  3. Reduces the strain on the server

We use webpack5 version or above, no terser-webpack-plugin, direct use can be.

Note: webpack4 requires installation!!

npm install terser-webpack-plugin --save-dev
Copy the code

However, we also need to execute the following command to install the related declaration file.

npm i --save-dev @types/terser-webpack-plugin
Copy the code

In the entry property of baseConfig, add a better-draggable-ball.min as a compressed version of the file.

entry: {
    'better-draggable-ball': './src/components/better-draggable-ball/index.ts'./ / better - draggable - ball plug-in
    'better-draggable-ball.min': './src/components/better-draggable-ball/index.ts'.// Better -draggable-ball plugin
  },
/ /... .
Copy the code

Add an Optimization object to baseConfig to compress files containing min.

optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: 4,
        include: /\.min\.js$/,
        terserOptions: {
          format: {
            comments: false,
          },
        },
        test: /\.js(\?.*)?$/i,
        extractComments: false,
      }),
    ],
  },
Copy the code

Adding the DevTool attribute to baseConfig enhances the debugging process by selecting a Source Map format. Different values can significantly affect the speed of build and rebuild (official explanation) for detailed configuration, see the Devtool configuration item

devtool:'cheap-module-source-map',
Copy the code

After configuration, run NPM run build to package the project ~ ~

In comparison to the packaged commonJS version of the plug-in, the compressed version (min.js) is about 50% less bulky than the uncompressed version, which greatly improves browser loading of the plug-in.

About the generated map file

A Source Map is an information file that stores location information. That is, every position in the transformed code corresponds to the position before the transformation. With this, browser developer tools call the Source Map to help with parsing, and in the event of an error, the debugger will display the original code directly instead of the transformed code. This undoubtedly brings great convenience in the debugging process.

This is because the configuration file above sets devtool

 devtool: 'cheap-module-source-map'
Copy the code

The last

This is the end of this series of tutorials, thank you for watching, I hope you found these three articles helpful!

If you have any suggestions for this article, please leave them in the comments section

😀😀 follow me and don’t get lost! 😀 😀