• 通过webpack创建并打包js库到npm仓库


    1.创建项目并进行基本配置

    webpack配置文件: webpack.build.js

    1. const path = require('path');
    2. module.exports = {
    3. mode:'development',
    4. entry:'./src/webpack-numbers.js',
    5. output: {
    6. filename: 'webpack-numbers.js',
    7. path: path.resolve(__dirname, 'dist'),
    8. clean: true,
    9. },
    10. };

    package.json:

    1. script:{
    2. "buildJs": "webpack --config ./webpack.build.js",
    3. "dev": "set NODE_ENV=development && webpack serve --open --config ./webpack.dev.js --mode=development",
    4. }

    2.暴露库:需要通过 output.library 配置项暴露从入口导出的内容

    注意:如果是暴露为ES Module时,不用同时设置name属性,build时会报错

    1. // 暴露库
    2. library: {
    3. // library.type设置为module时不能设置同时设置name
    4. type: 'module',
    5. },
    6. },

    3.使用库

    可以通过 script 标签使用,不演示

    4.运行在 ES6、CommonJS、AMD、Node.js 等环境中

    以上都只能通过script 标签使用,但是希望它能够兼容不同的环境

    解决:更新 output.library 配置项,将其 type 设置为 'umd'

    1. output: {
    2. path: path.resolve(__dirname, 'dist'),
    3. filename: 'webpack-numbers.js',
    4. library: {
    5. name: 'webpackNumbers',
    6. type: 'umd',
    7. },
    8. },

    我这里是将其导出为ES Module:

    注意:

    暴露为ES Module时,不能同时设置name属性;

    且需要在output同级设置experiments.outputModule为true

    1. mode:'development',
    2. entry:'./src/webpack-numbers.js',
    3. output: {
    4. filename: 'webpack-numbers.js',
    5. path: path.resolve(__dirname, 'dist'),
    6. clean: true,
    7. // 暴露库
    8. library: {
    9. // library.type设置为module时不能设置同时设置name
    10. type: 'module',
    11. },
    12. },
    13. // 设置 type: 'module'时,必须加入以下配置
    14. experiments: {
    15. outputModule: true,
    16. },

     

    5.library的type字段详解

    library 可接受的数据类型是 string | string[] | object。string 是 object 类型的简写形式,当值为 object 类型时,object 中能包含的属性有 name、type、export、auxiliaryComment 和 umdNamedDefine。本文将重点放在 type 字段上,它决定如何公开当前库,取值基本固定,name 字段可以是任何字符串,它用来指定库的名称。

    1.  library.type = var(默认值),{type: 'var', name: 'MyLibrary'}:通过MyLibrary能访问到add函数,但不能保证MyLibrary在全局变量上
    2.  library.type = window ,{type: 'window', name: 'MyLibrary'}:通过window.MyLibrary能访问到add函数。
    3. library.type = module,将 library 的值改成 {type: 'module'}, 此时还要 experiments.outputModule 设置为 true。此时不存在闭包,并且能用 es modules 将库导入。
    4. library.type = this,将 library 的值改成 {type: 'this', name: 'MyLibrary'},通过 this.MyLibrary 能访问到 add 函数;
    5. 将 library 的值改成 {type: 'self', name: 'MyLibrary'},此时通过 self.MyLibrary 可访问到 add 函数,在浏览器环境的全局上下文中 self 等于 window;
    6. 将 library 的值改成 {type: 'global', name: 'MyLibrary'},此时 MyLibrary 会被分配到全局对象,全局对象会根据target值的不同而不同,全部对象可能的值是 self、global 或 globalThis。当 target 的值为 web(默认值),此时的打包结果与 library.type = self 结果一样。
    7. library.type = commonjs,将 library 的值改成 {type: 'commonjs', name: 'MyLibrary'}
    8. 将 library 的值改成 {type: 'commonjs2', name: 'MyLibrary'},CommonJs 规范只定义了 exports ,但是 module.exports 被 node.js 和一些其他实现 CommonJs 规范的模块系统所使用,commonjs 表示纯 CommonJs,commonjs2 在 CommonJs 的基础上增加了 module.exports。
       

    webpack output.library的16 种取值方法示例_output.library.type-CSDN博客

    7.使用命令npm run buildJs打包时报错

    [webpack-cli] Error: Library name must be unset. Common configuration options that specific library names are 'output.library[.name]', 'entry.xyz.library[.name]', 'ModuleFederationPlugin.name' and 'ModuleFederationPlugin.library[.name]'.   

    [webpack-cli] Error: Library name must be unset. Common configuration options that specific library names are 'output.library[.name]', 'entry.xyz.library[.name]', 'ModuleFederationPlugin.name' and 'ModuleFederationPlugin.library[.name]'.   

    解决:library.type设置为module时不能设置同时设置name

    1. // 暴露库
    2. library: {
    3. // library.type设置为module时不能设置同时设置name
    4. //name:'tools',
    5. type: 'module',
    6. },

    6.外部化 lodash

    如果工具包中将lodash也打包进去包体积会很大,所以可以通过设置externals属性将lodash包进行隔离不打包,但是这要求使用工具包的项目环境下安装了lodash这个被隔离的包。

    1. externals: {
    2. lodash: {
    3. commonjs: 'lodash',
    4. commonjs2: 'lodash',
    5. amd: 'lodash',
    6. root: '_',
    7. },
    8. },

    7.问题:导出为ES6报错: 

    ERROR in external {"commonjs":"lodash","commonjs2":"lodash","amd":"lodash","root":"_"}
    Cannot read properties of undefined (reading 'length')
    TypeError: Cannot read properties of undefined (reading 'length')

    解决:配置ES6的外置依赖库 module: 'lodash'

    1. // 依赖工具库外置:要求引用的项目本身有这个工具库
    2. externals: {
    3. lodash: {
    4. commonjs: 'lodash',
    5. commonjs2: 'lodash',
    6. amd: 'lodash',
    7. // 配置ES module
    8. module: 'lodash',
    9. root: '_',
    10. },

    8.问题二:webpack 外部化lodash后报错,reduce()方法找不到

     将lodash外部化后,工具类中的引入lodash就不能再使用了,否则就会报错。注释掉引用即可用

    1. // 注意外部化的时候,这里引入就不能直接引入了
    2. // import _ from 'lodash';
    3. import numRef from './data/ref.json';
    4. export function numToWord(num) {
    5. return _.reduce(
    6. numRef,
    7. (accum, ref) => {
    8. return ref.num === num ? ref.word : accum;
    9. },
    10. ''
    11. );
    12. }
    13. export function wordToNum(word) {
    14. return _.reduce(
    15. numRef,
    16. (accum, ref) => {
    17. return ref.word === word && word.toLowerCase() ? ref.num : accum;
    18. },
    19. -1
    20. );
    21. }

    9.外部化的限制

    对于想要实现从一个依赖中调用多个文件的那些库,无法通过在 externals 中指定整个 library 的方式将它们从 bundle 中排除,而是需要逐个或者使用正则表达式排除它们。

    1. module.exports = {
    2. //...
    3. externals: [
    4. 'library/one',
    5. 'library/two',
    6. // 匹配以 "library/" 开始的所有依赖
    7. /^library\/.+$/,
    8. ],
    9. };

    10.优化生产环境下的输出结果

    为了优化生产环境下的输出结果。那么,我们还需要将生成 bundle 的文件路径,添加到 package.json 中的 main 字段中。

    1. {
    2. ...
    3. "main": "dist/webpack-numbers.js",
    4. ...
    5. }

    或者,按照这个 指南 将其添加为标准模块

    1. {
    2. ...
    3. "module": "src/webpack-numbers.js",
    4. ...
    5. }

    另外,为了暴露和库关联的样式表,你应该使用 MiniCssExtractPlugin。然后,用户可以像使用其他样式表一样使用和加载这些样式表。

    11.发布到npm仓库

    可以 将其发布为一个 npm 包,并且在 unpkg.com 找到它,并分发给你的用户。

    进入打包好后的文件夹dist,然后npm init 创建package.json文件,并且设置基本信息

    1. {
    2. "name": "webpack-numbers-lmf",
    3. "version": "1.0.4",
    4. "description": "修改",
    5. "main": "webpack-numbers.js",
    6. "private": false,
    7. "scripts": {
    8. "test": "echo \"Error: no test specified\" && exit 1"
    9. },
    10. "author": "limingfang",
    11. "license": "ISC"
    12. }

    npm login登录npm仓库

    命令行输入用户名和密码后npm publish发布版本即可

    12.使用:

    npm i webpack-numbers-lmf lodash -S
    1. import { numToWord,wordToNum } from "webpack-numbers-lmf"
    2. console.log(numToWord(3), wordToNum("Ten") );

    13.完整配置代码

    webpack.build.js:

    1. //webpack.build.js
    2. const path = require('path');
    3. module.exports = {
    4. mode:'development',
    5. entry:'./src/webpack-numbers.js',
    6. output: {
    7. filename: 'webpack-numbers.js',
    8. path: path.resolve(__dirname, 'dist'),
    9. clean: true,
    10. // 暴露库
    11. library: {
    12. // library.type设置为module时不能设置同时设置name
    13. type: 'module',
    14. },
    15. },
    16. // 设置 type: 'module'时,必须加入以下配置
    17. experiments: {
    18. outputModule: true,
    19. },
    20. // 依赖工具库外置:要求引用的项目本身有这个工具库
    21. externals: {
    22. lodash: {
    23. commonjs: 'lodash',
    24. commonjs2: 'lodash',
    25. amd: 'lodash',
    26. // 配置ES module
    27. module: 'lodash',
    28. root: '_',
    29. },
    30. },
    31. };
    1. //package.json
    2. {
    3. "name": "webpack-demo",
    4. "version": "1.0.0",
    5. "description": "",
    6. "private": false,
    7. "main": "dist/webpack-numbers.js",
    8. "module": "src/webpack-numbers.js",
    9. "scripts": {
    10. "buildJs": "webpack --config ./webpack.build.js",
    11. "dev": "set NODE_ENV=development && webpack serve --open --config ./webpack.dev.js --mode=development",
    12. "prod": "set NODE_ENV=production && webpack serve --open --config ./webpack.prod.js --mode=production"
    13. },
    14. ...
    15. }
    1. //webpack-numbers.js
    2. // 注意外部化的时候,这里引入就不能直接引入了
    3. // import _ from 'lodash';
    4. import numRef from './data/ref.json';
    5. export function numToWord(num) {
    6. return _.reduce(
    7. numRef,
    8. (accum, ref) => {
    9. return ref.num === num ? ref.word : accum;
    10. },
    11. ''
    12. );
    13. }
    14. export function wordToNum(word) {
    15. return _.reduce(
    16. numRef,
    17. (accum, ref) => {
    18. return ref.word === word && word.toLowerCase() ? ref.num : accum;
    19. },
    20. -1
    21. );
    22. }

    dist里的package.json

    1. {
    2. "name": "webpack-numbers-lmf",
    3. "version": "1.0.4",
    4. "description": "修改",
    5. "main": "webpack-numbers.js",
    6. "private": false,
    7. "scripts": {
    8. "test": "echo \"Error: no test specified\" && exit 1"
    9. },
    10. "author": "xxx",
    11. "license": "ISC"
    12. }

     使用:

    1. //index.js
    2. import _ from 'lodash';
    3. import { numToWord,wordToNum } from "webpack-numbers-lmf"
    4. function component() {
    5. console.log(numToWord(3), wordToNum("Ten") );
    6. return element;
    7. }
    8. document.body.appendChild(component());

  • 相关阅读:
    12.2排序
    注解及其使用
    负载均衡(SLB与ELB)
    PyCharm中 python 类型文件被识别为Text文本类型
    指针笔试题讲解(让指针变得简单易懂)
    UART相关参数和Modbus协议
    贝叶斯人工智能大脑与 ChatGPT
    神经多样性是什么意思,神经网络的可解释性差
    GDPU 数据结构 天码行空6
    mysql开启慢查询日志
  • 原文地址:https://blog.csdn.net/qq_34569497/article/details/133739180