全栈项目实践五:抽离npm包

本文内容学习自 哲玄前端 《大前端全栈实践》课程

当需要本地调试待发布的 npm 包时 在包的目录下(elpis)执行命令

bash 复制代码
npm link

在使用包的目录下(elpis-demo)执行命

bash 复制代码
npm link "name"
  • 这个 name 就是 elpis/package.json 中的name

关于静态资源目录

运行的时候一直会有 /view/project-list 的请求

  • elpis/app/view/entry.tpl 中使用了静态资源 /static/xxx
  • koaStatic 和 KoaNunjucks 配置的静态资源目录是 process.cwd()/app/public
    • 资源请求的是运行目录下的 elpis-demo/app/public
  • 实际资源还在 elpis/app/public/static/logo.png,但是 elpis-demo 中没有静态资源导致一直请求不到
  • 请求进入 elpis-core/loader/router.js 兜底策略一直请求 app.options.homePage

解决办法:将静态资源移动到 elpis-demo/public 中

devServer 和 element-plus 的按需加载

不能用element-plus的按需引入,不然 npm run build:dev 就一直卡在 webpack 的编译部分,npm run build:prod 就正常运行。

  • 虽然 devServer 正常启动了
  • 但是 webpack 的编译器根本没有启动,没有将源代码编译为 Bundle。
    • 第一步还得自己先手动编译一下(compiler.run),不然一直没编译,没有.tpl的输出。 启动静态服务器,但是没有HMR的效果,加watch只能监听变化,手动刷新才看得到。

自定义SSR页面的扩展

在 webpack.base.js 中修改 entry 和 HtmlWebpackPlugin 来获取全部的入口。

webpack里面的loader会在调用方里面的根目录开始找(即在 elpis-demo 的 node_modules)

  • 如果用自己 node_modules 的目录,改为 require.resolve()

    • 如果找不到包 用require.resolve()
  • 当这个 webpack 配置作为 npm 包被其他项目引用时,loader 的解析路径会基于 elpis 包本身,而不是调用方的 node_modules。

在 elpis-demo/app/pages 目录下写入口文件 entry.xxx.js 和对应组件

自定义 view 页面 dashboard/cutom-view

  1. 在 elpis-demo/app/pages/dashboard/xxx 写页面组件
  2. 在 elpis-demo/app/pages/dashboard/router.js 中进行配置
javascript 复制代码
module.exports = ({routes, siderRoutes}) => {}

当用户没配置 dashboard/router.js

  • try-catch无法解决
    • webpack是静态构建,并不是运行时构建,所以会直接报错
javascript 复制代码
try{
  businessDashboardRouterConfig = require('$businessDashboardRouterConfig')
}catch (e) {}
  • import的方式无法解决 依旧报错
javascript 复制代码
(async () => {
  businessDashboardRouterConfig = await import('$businessDashboardRouterConfig')
})()

解决方案

  1. 创建空文件让 webpack 别名指向它作为 fallback

    javascript 复制代码
          alias: (() => {
            const aliasMap = {}
            const blankModulePath = path.resolve(__dirname, '../libs/blankModule.js')
    
            const businessDashboardRouterConfigPath = path.resolve(process.cwd(), 'app/pages/dashboard/router.js')
            aliasMap['$businessDashboardRouterConfig'] = fs.existsSync(businessDashboardRouterConfigPath)
              ? businessDashboardRouterConfigPath
              : blankModulePath
    
            return {
              ...aliasMap,
            }
          })(),
    1. 简单、但是需要额外维护文件
  2. 编译时常量 + if 判断

    javascript 复制代码
          new webpack.DefinePlugin({
            __HAS_BUSINESS_DASHBOARD_ROUTER__: fs.existsSync() // true/false
          }),
    javascript 复制代码
        if(__HAS_BUSINESS_DASHBOARD_ROUTER__) {...}

    不会往 window 上挂变量;不会在运行时代码里真的出现 HAS..._ 这个名字。

    webpack 在构建时会做常量折叠:如果这个宏是 false,整块 if 分支会被摇掉
    2. 无额外文件,但是定义全局变量进行编译期宏替换

  3. 反向依赖------由业务入口调用基础库

动态组件扩展 dashboard/schema-view/components

  1. 在 app/pages/dashboard/complex-view/schema-view/components/ 下写组件
  • components的统一写法
javascript 复制代码
<script setup>
import { ref } from 'vue'

const name = ref('createForm')

const isShow = ref(false)

const show = () => {
  isShow.value = true
}

const close = () => {
  isShow.value = false
}

defineExpose({
  name,
  show,
})
</script>

<template></template>

<style scoped lang="less"></style>
  1. 配置app/pages/dashboard/complex-view/schema-view/components/component-config.js

schema-form 控件扩展

  1. 在app/pages/widgets/schema-form/complex-view/下写组件
xml 复制代码
<script setup>

const validate = () => {}

const getValue = () => {}

defineExpose({
  name,
  validate,
  getValue,
})
</script>

<template></template>

<style scoped lang="less"></style>
  1. 配置app/pages/widgets/schema-form/form-item-config.js
  1. 在app/pages/widgets/schema-search-bar/complex-view/下写组件
xml 复制代码
<script setup>

const reset = () => {}

const getValue = () => {}

defineExpose({
  reset,
  getValue,
})
</script>

<template></template>

<style scoped lang="less"></style>
  1. 配置app/pages/widgets/schema-search-bar/search-item-config.js

发布

bash 复制代码
npm config get registry
-> https://registry.npmjs.org/
如果不是, npm config set registry
bash 复制代码
npm login

npm whoami

npm publish --access public
相关推荐
wangruofeng24 分钟前
AI Models 1.1.0 发布,查大模型价格、对比模型和找 API 地址
前端·aigc·ai编程
wangruofeng27 分钟前
给前端开发者的 100 个设计参考网站
前端·设计
星栈4 小时前
视频即代码,Remotion 能做什么、不能做什么
前端·音视频开发
广州华水科技4 小时前
单北斗GNSS位移监测系统的应用与技术解析
前端
用户47949283569154 小时前
从一句话或代码仓到可交互 HTML:开源 Agent 画图技能 Archify v3.2 实测与选型边界
前端·后端·面试
风骏时光牛马6 小时前
生成一个AI多模态标题,仅输出一条标题,无额外文字、问句、备选、配图、文案等任何附加内容,不需要其他的任务服务 只要标题。
前端
wangruofeng7 小时前
从 GIF 到 AVIF:网页图片格式演进与 2026 年选型指南
前端·架构
清晨Coding8 小时前
为什么用 React Developer Tools 查看组件树这么乱?
前端·react.js
鶴哥只手遮天8 小时前
《Electron 45.2.3 内核解剖》第 4 章 补丁体系:380 个补丁改了什么
前端·electron
FungLeo10 小时前
成为全栈·Vue 管理后台篇·分类树与标签管理:层级数据如何落到管理界面
前端·javascript·vue.js·分类树·naive ui·标签管理·前端数据结构