全栈项目实践五:抽离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
相关推荐
paopaokaka_luck20 分钟前
宠物门店经营管理系统(销售与库存联动、进货自动记账、 退换与退款关联、员工个人业绩、ECharts 经营分析、滞销识别与客户分层、宠物档案年龄计算)
前端·javascript·spring boot·mysql·echarts·mybatis·1024程序员节
空中湖1 小时前
用 React 写数据大屏:为什么我不建议用图表库
前端·react.js·前端框架
欣欣之王来了2 小时前
原始HTML插值:v-html指令的使用与安全风险
前端·学习·架构·项目·vue3教程
IT_陈寒2 小时前
Redis的LRU淘汰策略坑了我一整天
前端·人工智能·后端
计算机魔术师3 小时前
砍半价格、参数再涨,国产旗舰追到 Opus 鼻尖了
前端
特立独行的猫A3 小时前
10 MB 的桌面 AI 客户端:用仓颉 + 系统 WebView 替代 Electron
前端·harmonyos
修炼的dance4 小时前
白底图存JPG,sharp开mozjpeg背景杂点少近三成
前端
anOnion4 小时前
构建无障碍组件之Grid Pattern
前端·html·交互设计
乔旭伟4 小时前
Vben3 中后台表格封装实战:useVbenVxeGrid 的全局收敛与七个坑
前端·anti-design-vue·1024程序员节
鶴哥只手遮天4 小时前
jQuery 4.0 源码架构与工程实践-第 10 章 尺寸、几何与显隐
前端·javascript·jquery