• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

webpack打包前端组件(三)

武飞扬头像
juejin
帮助179

前言

回顾前两篇文章中,我们从一个现成的webpack-template中,逐步逐步地修改构建出了一个组件调试的页面,当组件调试没问题之后,我们就要对组件进行一个打包操作让其他用户可以使用。

打包组件

执行npm run build命令进行项目打包 ~ ~

9.png

打包后分别有htmljs文件,我们使用编辑器打开Drag.html,发现html中已经帮我们引入了Drag.js了,其实在这里边它已经引入better-draggable-ball了,再使用浏览器打开后发现拖拽球是可以被正常显示出来的。

当我们重新创建一个HTML文件,引入better-draggable-ball时,再按原来ts中的写法会发现:

Drag is not defined

难道我们只能引入已经配置好配置项的Drag么???

强大的webpack也给我们提供了output.library选项,webpack打包时可以将你的项目作为一个库来导出

微信截图_20210624190019.png

关于 webpack library选项配置文档地址

我们修改webpack.config.ts配置文件,将我们的项目中的better-draggable-ball作为一个库来导出

web

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

output属性中添加library属性。

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

plugins属性中的HtmlWebpackPlugin进行删除,因为我们已经不需要导出HTML文件了,只需要导出js文件让其用户去引用就可以了。

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

附上完整的webpack.config.ts配置文件代码:

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 插件
  },
  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: [
          // 将 JS 字符串生成为 style 节点
          'style-loader',
          // 将 CSS 转化成 CommonJS 模块
          'css-loader',
          // 将 Sass 编译成 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;

接下来我们再打包一下,可以看到这次dist文件夹中只输出了better-draggable-ball文件。

微信截图_20210624195410.png

接下来,我们在dist文件夹中创建一个test.html文件,利用script标签引入一下,然后使用console.log来打印下betterDraggableBall看看里边是什么?

微信截图_20210624200736.png

很明显,打印出来的是个Object,里边只有一个default的函数,我们打印下试试。

微信截图_20210624215507.png

是一个函数,我们仔细一看,诶?这不是我们的Drag么?

我们试试看能不能new一下试试 。

!!! 注意:打包后 库的位置是在.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>

微信截图_20210624222304.png

webpack.config.ts中配置下library,让default中的数据作为默认导出对象,type属性是配置库的暴露方式,之后再打包一下

library: {
      name: 'betterDraggableBall',
      type: 'umd',
      export: 'default',
    },

打印下betterDraggableBall对象,这次我们可以看到没有default这个属性了,而是将default里的内容放到了betterDraggableBall对象根部了,也就是说现在可以直接直接new一个betterDraggableBall类了

微信截图_20210625143444.png

我们现在只达到了可以通过script标签来引入组件了

支持更多的引入方式

  • 定个小目标
    • 我们需要输出的文件是(分别为压缩和未压缩版本):
      • 一个 CommonJS 格式的 js 文件
      • 一个 UMD 格式的 js 文件
      • ESM格式的js文件

这里给大家简单的讲下这些格式

CommonJS

CommonJS是服务器端模块的规范,Node.js采用了这个规范。,主要语法:比如加载模块使用的是require方法,导出模块使用的是exportCommonJS 加载模块是同步的,所以只有加载完成才能执行后面的操作。

AMD

AMD 全称 Asyncchronous Module Definition,一般应用在浏览器端(这是与 CommonJS规范最大的不同点),最著名的 AMD 加载器是 RequireJS 。目前由于 webpack 的流行, AMD 这一模块化方案已逐渐退出市场。

UMD

UMDAMDCommonJS的糅合,以及最传统的全局变量模式。全局变量模式即是把库的入口挂载在一个全局变量(window.xxx)上,页面上的任何位置都能随时取用,属于最传统的 js 插件加载方案,它的出现也是解决跨平台的问题。UMD先判断是否支持Node.js的模块(exports)是否存在,存在则使用Node.js模块模式。在判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块。

ESM

esm 即 es6 模块,在之前常用的是 CommonJS 和基于 AMD 的其他模块系统,ES Modules 的关键字是 importexport,也是目前最流行的一种导入方式。

我们需要修改webpack的配置文件,之前我们打包项目都是使用单独的一种配置方式,但是我们现在需要导出多种类型文件,这时webpack给我们提供了导出多种配置方式的写法(webpack 3.1.0 起支持),把webpack.config.ts修改如下:

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 插件
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.s[ac]ss$/i,
        use: [
          // 将 JS 字符串生成为 style 节点
          'style-loader',
          // 将 CSS 转化成 CommonJS 模块
          'css-loader',
          // 将 Sass 编译成 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;

这里边,我定义了2个数组,一个是baseConfig,它用来存放webpackConfig的基本配置,另外一个是outputConfig,它存放了三种导出方式,分别为commonjsumdmodule,最后我使用了循环和对象合并方法把基本配置对象和不同的output属性进行一个合并生成导出一个新的webpackConfig模块。

// 合并的语句
const config:webpackConfiguration[]|[] = [];
for (let i: number = 0; i < outputConfig.length; i  = 1) {
  config[i] = Object.assign(outputConfig[i], baseConfig);
}

我们打包试一下,看看是不是生成了多种导入方式的文件:

2.png

nice!接下来我们创建一个普通的HTML文件使用script标签引用试一下(umd)。

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

3.png

接下来,再试试ESM版本的,这里我新建了一个vue vite项目,在项目中的组件中引入它。

  // 忽略一些代码  只列出主要代码
  import Drag from './better-draggable-ball'
 
  setup: () => {
    const DragDom=ref<HTMLElement|null>(null)
    // 拖拽组件 初始化
    onMounted(()=>{
      new Drag(DragDom.value, {
        defaultPosition: { x: 10, y: 10 },
        autoAdsorbent: true,
      });
    })
    return{
      DragDom
    }
  }

77.gif

压缩环节

为什么要进行压缩处理

通常,开源的插件、库代码都会提供两种版本:

  1. 可读版,一般为开发人员准备的
  2. 压缩版,一般为生产环境中提供使用的

压缩版的好处:

  1. 减少了文件的体积
  2. 减少了网络传输时使用的带宽占用
  3. 减少了服务器的压力

我们使用的是webpack5版本以上的,无需terser-webpack-plugin插件,直接使用就可以了。

注意:webpack4版本需要安装!!

npm install terser-webpack-plugin --save-dev

但我们还需要执行下以下命令,安装相关声明文件。

npm i --save-dev @types/terser-webpack-plugin

baseConfig的入口属性中,添加一个better-draggable-ball.min,作为压缩版的文件。

entry: {
    'better-draggable-ball': './src/components/better-draggable-ball/index.ts', // better-draggable-ball 插件
    'better-draggable-ball.min': './src/components/better-draggable-ball/index.ts', // better-draggable-ball 插件(压缩版本)
  },
// ... ...

baseConfig中添加optimization对象,将含有min的文件进行压缩处理。

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

baseConfig中添加devtool属性,是选择一种 source map 格式来增强调试过程。不同的值会明显影响到构建(build)和重新构建(rebuild)的速度 ( 官方解释 )详细配置请阅读 Devtool 配置项

devtool:'cheap-module-source-map',

配置完之后,执行npm run build将项目进行打包 ~ ~

6.png

拿打包后的commonjs版本的插件对比一下,压缩版本(min.js)比未压缩版本减少了约50%的体积,这大大提升了浏览器加载该插件的速度。

关于生成后的map文件

Source map就是一个信息文件,里面储存着位置信息。也就是说,转换后的代码的每一个位置,所对应的转换前的位置。有了它,浏览器开发者工具会调用 source map 来帮助解析,在出错的时候,除错工具将直接显示原始代码,而不是转换后的代码。这无疑在调试过程中带来了很大方便。

这是因为上面的配置文件设置了devtool

 devtool: 'cheap-module-source-map'

最后

本系列的教程也到此结束了,很感谢大家的观看,希望这三篇文章对大家有所帮助!

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanekki
系列文章
更多 icon
同类精品
更多 icon
继续加载