最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 完结!手把手教你使用webpack打包前端组件(三)

    正文概述 掘金(_island)   2021-06-28   594

    手把手教你使用webpack打包前端组件(三)

    这是我参与更文挑战的第9天,活动详情查看: 更文挑战

    回顾前面

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

    如果还没有阅读第一,二篇的小伙伴们, 请点击阅读: 手把手教你使用webpack打包前端组件(一)

    手把手教你使用webpack打包前端组件(二)

    打包组件

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

    完结!手把手教你使用webpack打包前端组件(三)

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

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

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

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

    完结!手把手教你使用webpack打包前端组件(三)

    我们修改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文件。

    完结!手把手教你使用webpack打包前端组件(三)

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

    完结!手把手教你使用webpack打包前端组件(三)

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

    完结!手把手教你使用webpack打包前端组件(三)

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

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

    <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>
    

    完结!手把手教你使用webpack打包前端组件(三)

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

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

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

    完结!手把手教你使用webpack打包前端组件(三)

    我们现在只达到了可以通过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);
    }
    

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

    完结!手把手教你使用webpack打包前端组件(三)

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

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

    完结!手把手教你使用webpack打包前端组件(三)

    接下来,再试试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
        }
      }
    

    完结!手把手教你使用webpack打包前端组件(三)

    压缩环节

    为什么要进行压缩处理

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

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

    压缩版的好处:

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

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

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

    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将项目进行打包 ~ ~

    完结!手把手教你使用webpack打包前端组件(三)

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

    关于生成后的map文件

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

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

     devtool: 'cheap-module-source-map'
    

    最后

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

    如果你对文章有什么建议可以留言在评论区哦

    ?? 关注我,不迷路! ??


    起源地下载网 » 完结!手把手教你使用webpack打包前端组件(三)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元