构建NodeJS库--前端项目的打包发布

embedded/2024/9/25 4:28:07/

1. 前言

学习如何打包发布前端项目,需要学习以下相关知识:

  • package.json 如何初始化配置,以及学习npm配置项;
    • 模块类型type配置, 这是nodejs的package.json的配置
    • main 入口文件的配置
  • webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具,使用说明,推荐阅读;
  • babel-loader JavaScript通常需要做语法转化和polyfills以便可以使用高级语法而不必担心浏览器兼容性问题,Babel的作用便在于此,而babel-loader正好可以与webpack结合使用;
  • eslint 一个好的项目离不开代码格式规范;
  • jest 一款js测试框架,写好测试用例覆盖测试的功能点,确保软件质量,推荐阅读;

2. 概念区别

Node.js是JavaScript的一种运行环境,是对Google V8引擎进行的封装。是一个服务器端的JavaScript的解释器。npm(Node Package Manager)是nodejs的包管理器。

有一些概念容易混淆,注意区分。

2.1 CommonJS vs Es module

关于type的配置值有:

  • module 可以指示 Node.js 通过使用.cjs扩展名命名特定文件,将其解释为CommonJS
  • commonjs 可以通过使用.mjs扩展名命名特定文件,指示 Node.js 将其解释为 ES module

ps:js文件两种类型都能识别。

ES module 更加现代化和灵活,支持动态导入、异步加载、静态作用域等特性,

而 CommonJS 更加简单和适用于早期的 Node.js 环境。

在实际开发中,需要根据具体的项目需求和环境来选择使用哪种模块系统。

看到深入浅出 Commonjs 和 Es Module一文描述的很详细,感兴趣可以详细了解。

2.2 package.json入口mainmodulebrower

总结:其他项目引用时,会根据项目自身的type来选择定义的lib的入口文件,三个配置的主要区别在于优先级。

一般通常认为browser = browser+mjs > module > browser+cjs > main

推荐阅读入口文件配置的区别一文。

2.3 ES5 vs ES6

  • ES5指的是ECMScript的第五个版本,发布于2009年,是目前最广泛使用的JavaScript版本。
  • ES6是ECMScript的第六个版本,也成为ES2015,发布于2015年,引入了许多新的语言特性和语法糖。
  • ES2015是ES6的官方名称,但是由于ES6引入了太多的新特性,因此人们通常使用ES2015来指代ES6。

推荐阅读ES5和ES6的区别以及ES6常用特性

webpack_config_outputlibrarytype_42">2.4 webpack config中的 output.library.type

官方使用说明中配置可选项很多,这里介绍:

  • commonjs
  • module
  • umd 统一模块定义,这种模块语法,兼容了以上的CommonJS、AMD、ES Module使用方式,也就是Vue脚手lib模式打包的这种模式,设置改值后,注意globalObject配置项可设置值为'this'

推荐阅读CommonJS/AMD/UMD/ES Module介绍和区别

3. 项目实战

源码:https://github.com/SkylerHu/js-enum

3.1 目录结构

在这里插入图片描述

3.2 主要配置文件

3.2.1 .babelrc

{"presets": ["@babel/preset-env"],"plugins": ["@babel/plugin-proposal-class-properties"]
}

3.2.2 .eslintignore

# node_modules
node_modules/# build
build/# dist
dist/
docs/

3.2.3 .estlintrc.json

{"env": {"browser": true,"es6": true,"mocha": true,"jest": true,"node": true},"globals": {"dashjs": true,"WebKitMediaSource": true,"MediaSource": true,"WebKitMediaKeys": true,"MSMediaKeys": true,"MediaKeys": true},"parser": "babel-eslint","rules": {"no-caller": 2,"no-undef": 2,"no-unused-vars": 2,"no-use-before-define": 0,"object-curly-spacing": ["error", "always"],"strict": 0,"semi": 2,"no-loop-func": 0,"no-multi-spaces": "error","keyword-spacing": ["error",{"before": true,"after": true}],"quotes": ["error","single",{"allowTemplateLiterals": true}],"indent": ["error",2,{"SwitchCase": 1}]},"ignorePatterns": ["releases/**/*"],"overrides": [{"files": ["tests/**/*"],"env": {"jest": true}}]
}

3.2.3 jest.config.json

{"verbose": true,"collectCoverage": true,"coverageDirectory": "./.coverage","moduleFileExtensions": ["js","json"],"testMatch": ["**/tests/**/*.js"],"collectCoverageFrom": ["src/**/*.{js,jsx}","!**/node_modules/**"],"testEnvironment": "node"
}

3.2.2 package.json

{"author": "SkylerHu","name": "js-enumerate","version": "1.0.2","private": false,"type": "module","main": "dist/index.js","files": ["dist"],"publishConfig": {"access": "public","registry": "https://registry.npmjs.org/"},"engines": {"node": "^14.21.3"},"scripts": {"lint": "eslint .","lint:fix": "eslint . --fix","build": "webpack --config webpack.config.js","test": "jest"},"dependencies": {},"devDependencies": {"@babel/core": "^7.24.4","@babel/plugin-proposal-class-properties": "^7.18.6","@babel/preset-env": "^7.24.4","@jest/globals": "^29.7.0","babel-eslint": "^10.1.0","babel-loader": "^9.1.3","clean-webpack-plugin": "^4.0.0","eslint": "7.32.0","eslint-loader": "^4.0.2","identity-obj-proxy": "^3.0.0","jest": "^29.7.0","jest-environment-jsdom": "^29.7.0","webpack": "^5.91.0","webpack-cli": "^5.1.4"},"description": "Enum is a javascript enumeration module. It works with Node.js and the browser.","keywords": ["enum","enumerate","javascript","js-enum","js-enumerate","react-enum","vue-enum"],"homepage": "https://github.com/SkylerHu/js-enum","repository": {"type": "git","url": "git@github.com:SkylerHu/js-enum.git"},"bugs": {"url": "https://github.com/SkylerHu/js-enum/issues"},"license": "MIT"
}

3.2.3 webpack.config.js

import path from 'path';
import { CleanWebpackPlugin } from 'clean-webpack-plugin';import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';const __dirname = dirname(fileURLToPath(import.meta.url));const PATHS = {src: path.join(__dirname, 'src'),build: path.join(__dirname, 'dist'),
};const config = {mode: 'production',// devtool: 'source-map',entry: path.join(PATHS.src, 'index.js'),output: {path: PATHS.build,clean: true,filename: 'index.js',library: {name: 'Enum',type: 'umd', // 采用通用模块定义export: 'default', // 兼容 ES6 的模块系统、CommonJS 和 AMD 模块规范},globalObject: 'this',},resolve: {extensions: ['.js', '.jsx', '.json'],},module: {rules: [{test: /\.(js|jsx)$/,exclude: /node_modules/, //排除node_modules文件夹enforce: 'pre', //提前加载使用use: { //使用eslint-loader解析loader: 'eslint-loader'}},{// 使用 babel-loader 来编译处理 js 和 jsx 文件test: /\.(js|jsx)$/,exclude: /node_modules/,use: {loader: 'babel-loader',},}]},plugins: [new CleanWebpackPlugin(),],optimization: {minimize: true,},
};export default config;

3.3 如何构建发版

  • 安装依赖npm install .
  • 代码格式npm run lint
  • 测试用例npm run test
  • 构建npm run build
  • 发版npm publish ,具体命令可以npm help查看,也可以查看官方文档
    • 需要在nodejs.org上注册账号,可以npm adduser通过命令行操作;
    • publish前需要npm login登录账号;
    • 也可以直接npmrc配置中配置好账号,或者创建auth_token配置

3.4 其他注意的问题

  • 3.4.1 jestwebpack版本对node版本的要求,node版本可以通过nvm控制;
> jest
./node_modules/jest/node_modules/jest-cli/build/run.js:135if (error?.stack) {^
SyntaxError: Unexpected token '.'

升级node版本解决,该项目使用的node 14+

语法标准中,可选链运算符(?.) 要求node版本14+

  • 3.4.2 Babel编译缺少plugin
> jestFAIL  tests/test_enum.js● Test suite failed to runJest encountered an unexpected tokenJest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax....Details:SyntaxError: ./src/index.js: Missing class properties transform.8 |9 | export default class Enum {> 10 |   #items = [];|   ^^^^^^^^^^^^11 |   #config = {};12 |   /**13 |    *

通过安装和配置@babel/plugin-proposal-class-properties解决,参考

  • 3.4.3 webpack配置output.type为umd时,注意配置globalObject: 'this'
file:///.../node_modules/js-enumerate/dist/index.js:1
ReferenceError: self is not definedat file:///Users/skyler/Documents/github/test/node_modules/js-enumerate/dist/index.js:1:190at ModuleJob.run (internal/modules/esm/module_job.js:183:25)at async Loader.import (internal/modules/esm/loader.js:178:24)at async Object.loadESM (internal/process/esm_loader.js:68:5)at async handleMainPromise (internal/modules/run_main.js:59:12)

报错参考typescript-webpack-library-generates-referenceerror-self-is-not-defined解决。

  • 3.4.4 当nodejs.org上仅publish一个版本,操作npm unpublish后,导致无法找寻项目名,24小时内无法再次publish
    • 具体阅读关于取消版本发布的说明;
npm ERR! code E403
npm ERR! 403 403 Forbidden - PUT https://registry.npmjs.org/js-enumerate - js-enumerate cannot be republished until 24 hours have passed.
npm ERR! 403 In most cases, you or one of your dependencies are requesting
npm ERR! 403 a package version that is forbidden by your security policy.npm ERR! A complete log of this run can be found in:
npm ERR!     ./.npm/_logs/2024-04-21T18_27_39_505Z-debug.log

http://www.ppmy.cn/embedded/12125.html

相关文章

电子信息制造工厂5G智能制造数字孪生可视化平台,推进数字化转型

电子信息制造工厂5G智能制造数字孪生可视化平台,推进数字化转型。5G智能制造数字孪生可视化平台利用5G网络的高速、低延迟特性,结合数字孪生技术和可视化界面,为电子信息制造工厂提供了一种全新的生产管理模式。不仅提升生产效率,…

程序猿成长之路之数据挖掘篇——朴素贝叶斯

朴素贝叶斯是数据挖掘分类的基础,本篇文章将介绍一下朴素贝叶斯算法 情景再现 以挑选西瓜为例,西瓜的色泽、瓜蒂、敲响声音、触感、脐部等特征都会影响到西瓜的好坏。那么我们怎么样可以挑选出一个好的西瓜呢? 分析过程 既然挑选西瓜有多个…

酷开科技逐步为用户构建健全的智慧家庭生活场景

大规模与精细化人群技术则是通过大量的计算能力和精细化的运营能力,建立用户专属数据储存区域,使得用户在使用不同电视的观影偏好和兴趣能够能够得以延续。 不拘泥于自有品牌终端数量,酷开系统除了集成在创维电视上,还服务于飞利…

gitlab关联新仓库

如果你想要将现有的Git仓库提交(或推送)到一个新的远程地址,你可以通过以下步骤来完成: 查看现有的远程仓库: 首先,确认你当前的仓库有哪些远程地址。 git remote -v如果输出中显示了旧的远程地址&#x…

如何在Android应用中安全地使用SQLite数据库,并通过SQLCipher进行加密保护

Android内置SQLite轻量级关系型数据库,可以在Android应用中存储、检索和管理结构化数据。SQLite是一个无服务器的、零配置的、事务性的SQL数据库引擎,非常适合用于移动设备和桌面应用程序中。 SQLite特点: 「轻量级」:SQLite不需要单独的服务器进程或操作系统级别的配置。…

[论文阅读链接]

CVPR2023:Learning Human-to-Robot Handovers from Point Clouds http://t.csdnimg.cn/OfSnShttp://t.csdnimg.cn/OfSnS仿真工具:dm_control: Software and Tasks for Continuous Control dm_control 翻译: Software and Tasks for Continuous Control…

FPGA秋招-笔记整理(1)

一、关键路径 关键路径通常是指同步逻辑电路中,组合逻辑时延最大的路径(这里我认为还需要加上布线的延迟),也就是说关键路径是对设计性能起决定性影响的时序路径。也就是静态时序报告中WNS(Worst Nagative Slack&…

信息系统项目管理师0066:过程管理(5信息系统工程—5.1软件工程—5.1.6过程管理)

点击查看专栏目录 文章目录 5.1.6过程管理1.成熟度模型2.成熟度等级5.1.6过程管理 软件过程能力是组织基于软件过程、技术、资源和人员能力达成业务目标的综合能力。包括治理能力、开发与交付能力、管理与支持能力、组织管理能力等方面。软件过程能力成熟度是指组织在提升软件产…