当前位置:首页>焦点 > 正文

天天热资讯!从0到1构建基于自身业务的前端工具库

  • 2023-04-10 16:38:37来源:博客园

作者:京东零售 吴迪

前言

在实际项目开发中无论 M 端、PC 端,或多或少都有一个 utils 文件目录去管理项目中用到的一些常用的工具方法,比如:时间处理、价格处理、解析url参数、加载脚本等,其中很多是重复、基础、或基于某种业务场景的工具,存在项目间冗余的痛点以及工具方法规范不统一的问题。

在实际开发过程中,经常使用一些开源工具库,如 lodash,以方便、快捷的进行项目开发。但是当 npm上没有自己中意或符合自身业务的工具时,我们不得不自己动手,此时拥有自己的、基于业务的工具库就显得尤为重要。我们所熟知的Vue、React等诸多知名前端框架,或公司提供的一些类库,它们是如何开发、构建、打包出来的,本文将带领你了解到如何从0到1构建基于自身业务的前端工具库。构建工具库主流方案1. WEBPACKwebpack 提供了构建和打包不同模块化规则的库,只是需要自己去搭建开发底层架构。vue-cli,基于 webpack , vue-cli 脚手架工具可以快速初始化一个 vue 应用,它也可以初始化一个构建库。2. ROLLUProllup 是一个专门针对JavaScript模块打包器,可以将应用或库的小块代码编译成更复杂的功能代码。Vue、React 等许多流行前端框架的构建和打包都能看到 rollup 的身影。为什么采用 ROLLUP 而不是 WEBPACKwebpack 主要职能是开发应用,而 rollup 主要针对的就是 js 库的开发,如果你要开发 js 库,那 webpack 的繁琐配置和打包后的文件体积就不太适用了,通过webpack打包构建出来的源代码增加了很多工具函数以外的模块依赖代码。rollup 只是把业务代码转码成目标 js ,小巧且轻便。rollup对于代码的Tree-shaking和ES6模块有着算法优势上的支持,如果只想构建一个简单的库,并且是基于ES6开发的,加上其简洁的API,rollup得到更多开发者的青睐。工具库底层架构设计

构建工具库底层架构大概需要哪些功能的支持:


(资料图)

架构依赖需知

在对底层架构设计的基础上,首先需要把用到的依赖库简单熟悉一下:

rollup 全家桶

•  rollup(工具库打包构建核心包)

•  rollup-plugin-livereload(rollup 插件,热更新,方便本地 debugger 开发)

•  rollup-plugin-serve(rollup 插件,本地服务代理,方便在本地 html 中调试工具)

•  rollup-plugin-terser(rollup 插件,代码压缩混淆)

•  rollup-plugin-visualizer(rollup 插件,可视化并分析 Rollup bundle,以查看模块占用)

•  @rollup/plugin-babel(rollup 插件,rollup 的 babel 插件,ES6 转 ES5)

•  @rollup/plugin-commonjs(rollup 插件,用来将 CommonJS 模块转换为 ES6,这样它们就可以包含在 Rollup 包中)

•  @rollup/plugin-json(rollup 插件,它将.json 文件转换为 ES6 模块)

•  @rollup/plugin-node-resolve(rollup 插件,它使用节点解析算法定位模块,用于在节点模块中使用第三方 node_modules 包)

•  @rollup/plugin-typescript(rollup 插件,对 typescript 的支持,将 typescript 进行 tsc 转为 js)

typescript 相关

•  typescript(使用 ts 开发工具库)

•  tslib(TypeScript 的运行库,它包含了 TypeScript 所有的帮助函数)

•  @typescript-eslint/eslint-plugin(TypeScript 的 eslint 插件,约束 ts 书写规范)

•  @typescript-eslint/parser(ESLint 解析器,它利用 TypeScript ESTree 来允许 ESLint 检测 TypeScript 源代码)

文档相关

•  typedoc(TypeScript 项目的文档生成器)

•  gulp(使用 gulp 构建文档系统)

•  gulp-typedoc(Gulp 插件来执行 TypeDoc 工具)

•  browser-sync(文档系统热更新)

单元测试相关

•  jest(一款优雅、简洁的 JavaScript 测试框架)

•  @types/jest(Jest 的类型定义)

•  ts-jest(一个支持源映射的 Jest 转换器,允许您使用 Jest 来测试用 TypeScript 编写的项目)

•  @babel/preset-typescript(TypeScript 的 Babel 预设)

其他依赖

•  eslint(代码规范约束)

•  @babel/core(@rollup/plugin-babel 依赖的 babel 解析插件)

•  @babel/plugin-transform-runtime(babel 转译依赖)

•  @babel/preset-env(babel 转译依赖)

•  chalk(控制台字符样式)

•  rimraf(UNIX 命令 rm -rf 用于 node)

•  cross-env(跨平台设置 node 环境变量)

底层架构搭建1. 初始化项目

新建一个文件夹 utils-demo,执行 npm init,过程会询问构建项目的基本信息,按需填写即可:

npm init
2. 组织工具库业务开发 SRC 目录结构

创建工具库业务开发 src 文件目录,明确怎样规划工具库包,里面放置的是工具库开发需要的业务代码:

3. 安装项目依赖

要对 typescript 代码进行解析支持需要安装对 ts 支持的依赖,以及对开发的工具的一些依赖包:

yarn add typescript tslib rollup rollup-plugin-livereload rollup-plugin-serve rollup-plugin-terser rollup-plugin-visualizer @rollup/plugin-babel @rollup/plugin-commonjs @rollup/plugin-json @rollup/plugin-node-resolve @rollup/plugin-typescript @babel/core @babel/plugin-transform-runtime @babel/preset-env rimraf lodash chalk@^4.1.2 -D

这里遇到一个坑,关于最新 chalk5.0.0 不支持在 nodejs 中 require()导入,所以锁定包版本 chalk@^4.1.2

要对 typescript 进行解析和编译还需要配置 tsconfig.json,该文件中指定了用来编译这个项目的根文件和编译选项,在项目根目录,使用 tsc --init 命令快速生成 tsconfig.json 文件(前提全局安装 typescript)

npm i typescript -gtsc --init

初始化 tsconfig 完成之后,根目录自动生成 tsconfig.json 文件,需要对其进行简单的配置,以适用于 ts 项目,其中具体含义可以参考tsconfig.json官网

4. 组织项目打包构建 SCRIPTS 目录结构根目录创建项目打包构建 scripts 脚本文件目录,里面放置的是有关于项目打包构建需要的文件:

生成rollup配置项函数核心代码:

const moduleName = camelCase(name) // 当format为iife和umd时必须提供,将作为全局变量挂在window下:window.moduleName=...const banner = generateBanner() // 包说明文案// 生成rollup配置文件函数const generateConfigs = (options) => {  const { input, outputFile } = options  console.log(chalk.greenBright(`获取打包入口:${input}`))  const result = []  const pushPlugins = ({ format, plugins, ext }) => {    result.push({      input, // 打包入口文件      external: [], // 如果打包出来的文件有项目依赖,可以在这里配置是否将项目依赖一起打到包里面还是作为外部依赖      // 打包出口文件      output: {        file: `${outputFile}${ext}`, // 出口文件名称        sourcemap: true, // // 是否生成sourcemap        format, // 打包的模块化格式        name: moduleName, // 当format为iife和umd时必须提供,将作为全局变量挂在window下:window.moduleName=...        exports: "named" /** Disable warning for default imports */,        banner, // 打包出来的文件在最顶部的说明文案        globals: {} // 如果external设置了打包忽略的项目依赖,在此配置,项目依赖的全局变量      },      plugins // rollup插件    })  }  buildType.forEach(({ format, ext }) => {    let plugins = [...defaultPlugins]    // 生产环境加入包分析以及代码压缩    plugins = [      ...plugins,      visualizer({        gzipSize: true,        brotliSize: true      }),      terser()    ]    pushPlugins({ format, plugins, ext })  })return result}
rollup 在打包构建的过程中需要进行 babel 的转译,需要在根目录添加.babelrc 文件告知 babel:
{  "presets": [    [      "@babel/preset-env"    ]  ],  "plugins": ["@babel/plugin-transform-runtime"]}
此时距离打包构建工具库只差一步之遥,配置打包脚本命令,在 package.json 中配置命令:
"scripts": {    "build": "rimraf lib && rollup -c ./scripts/rollup.config.js" // rollup打包 },
执行 yarn build,根目录会构建出一个 lib 文件夹,里面有打包构建的文件,还多了一个 stats.html,这个是可视化并分析 Rollup bundle,用来查看工具模块占用空间:架构搭建优化

项目搭建到这里,不知机智的你能否发现问题:

只要添加了一个工具,就要在入口文件导出需要打包构建的工具,在多人开发提交代码的时候将引来冲突的产生:使用工具库的时候,按需引用的颗粒度太细了,不能满足一些要求颗粒度粗的朋友,比如:

• 我想使用该包里面 date 相关工具,要这样吗?

import { dateA, dateB, dateC } from "utils-demo"

能不能这样?

import { date } from "utils-demo"date.dateA()date.dateB()date.dateC()

• 在一些使用 script 脚本引入的场景下,就仅仅需要 date 相关的工具,要这样吗?

<script src="https://xxx/main.min.js">

能不能这样?

<script src="https://xxx/date.min.js">

这样仅仅使用 date 里面的工具,就没有必要将所有的工具都引入了

解决方案:

针对第一个代码冲突的问题,可以根据 src > modules 下目录结构自动生成入口文件 index.ts

自动构建入口文件核心代码:

const fs = require("fs") // node fs模块const chalk = require("chalk") // 自定义输出样式const { resolveFile, getEntries } = require("./utils")let srcIndexContent = `// tips:此文件是自动生成的,无需手动添加`getEntries(resolveFile("src/modules/*")).forEach(({ baseName, entry }) => {  let moduleIndexContent = `// tips:此文件是自动生成的,无需手动添加`  try {    // 判断是否文件夹    const stats = fs.statSync(entry)    if (stats.isDirectory()) {      getEntries(`${entry}/*.ts`).forEach(({ baseName }) => {        baseName = baseName.split(".")[0]        if (baseName.indexOf("index") === -1) {          moduleIndexContent += `export * from "./${baseName}"`        }      })      fs.writeFileSync(`${entry}/index.ts`, moduleIndexContent, "utf-8")      srcIndexContent += `export * from "./modules/${baseName}"export * as ${baseName} from "./modules/${baseName}"`    } else {      srcIndexContent += `export * from "./modules/${baseName.split(".")[0]}"`    }  } catch (e) {    console.error(e)  }})fs.writeFileSync(resolveFile("src/index.ts"), srcIndexContent, "utf-8")
针对颗粒度的问题,可以将 modules 下各种类型工具文件夹下面也自动生成入口文件,除了全部导出,再追加 import * as 模块类名称 类型的导出

至此,基本上解决了工具库打包的问题,但是架构中还缺少本地开发调试的环境,下面为大家介绍如何架构中添加本地开发调试的系统。

本地开发调试系统

首先要明确要加入本地开发调试系统的支持,需要做到以下:

• 跨平台(window不支持NODE_ENV=xxx)设置环境变量,根据环境配置不同的 rollup 配置项

• 引入本地开发需要的 html 静态服务器环境,并能做到热更新

跨平台设置环境变量很简单,使用 cross-env 指定 node 的环境
yarn add cross-env -D
配置 package.json 命令
"scripts": {    "entry": "node ./scripts/build-entry.js",    "dev": "rimraf lib && yarn entry && cross-env NODE_ENV=development rollup -w -c ./scripts/rollup.config.js", // -w 表示监听的工具模块的修改    "build": "rimraf lib && yarn entry && cross-env NODE_ENV=production rollup -c ./scripts/rollup.config.js"  },
根据最开始架构设计的模块,在项目根目录新建 debugger 文件夹,里面存放的是工具调试的 html 静态页面接下来就是配置 scripts > rollup.config.js ,将 NODE_ENV=development 环境加入 rollup 配置,修改生成rollup配置项函数核心代码:
(isProd ? buildType : devType).forEach(({ format, ext }) => {    let plugins = [...defaultPlugins]    if (isProd) {      // 生产环境加入包分析以及代码压缩      plugins = [...plugins, visualizer({        gzipSize: true,        brotliSize: true      }), terser()]    } else {      // 非生产环境加入热更新和本地服务插件,方便本地debugger      plugins = [...plugins, ...[        // 热更新        rollUpLiveLoad({          watch: ["debugger", "lib"],          delay: 300        }),        // 本地服务代理        rollupServe({          open: true,          // resolveFile("")代理根目录原因是为了在ts代码里debugger时可以方便看到调试信息          contentBase: [resolveFile("debugger"), resolveFile("lib"), resolveFile("")]        })      ]]    }    pushPlugins({ format, plugins, ext })  })
执行 yarn dev 之后浏览器会新打开窗口,输入刚添加的工具链接,并且它是热更新的:工具库文档系统

一个完备的工具库需要有一个文档来展示开发的工具函数,它可能需要具备以下几点支持:

• 支持工具库中方法的可视化预览

• 支持修改工具的时候,具备热更新机制

typedoc(TypeScript 项目的文档生成器)能完美支持 typescript 开发工具库的文档生成器的支持,它的核心原理就是读取源代码,根据工具的注释、ts的类型规范等,自动生成文档页面

关于热更新机制的支持,第一个自然想到 browser-sync(文档系统热更新)

由于文档系统的预览功能有很多插件组合来实现的,可以借助 gulp (基于流的自动化构建工具),typedoc正好有对应的 gulp-typedocGulp 插件来执行 TypeDoc 工具插件

构建完成后打开文档系统,并且它是热更新的,修改工具方法后自动更新文档:

单元测试

为确保用户使用的工具代码的安全性、正确性以及可靠性,工具库的单元测试必不可少。单元测试选用的是 Facebook 出品的 Jest 测试框架,它对于 TypeScript 有很好的支持。

1. 环境搭建首先全局安装 jest 使用 init 来初始化 jest 配置项
npm jest -gjest --init下面是本人设置的jest的配置项✔ Would you like to use Jest when running "test" script in "package.json"? … yes✔ Would you like to use Typescript for the configuration file? … yes✔ Choose the test environment that will be used for testing › jsdom (browser-like)✔ Do you want Jest to add coverage reports? … yes✔ Which provider should be used to instrument code for coverage? › babel✔ Automatically clear mock calls, instances and results before every test? … yes

执行完之后根目录会自动生成jest.config.ts 文件,里面设置了单元测试的配置规则,package.json 里面也多了一个 script 指令 test。

关于jest.config.js文件配置项具体含义可以查看官网,要想完成 jest 对于 TypeScript 的测试,还需要安装一些依赖:
yarn add jest ts-jest @babel/preset-typescript @types/jest -D
jest 还需要借助 .babelrc 去解析 TypeScript 文件,再进行测试,编辑 .babelrc 文件,添加依赖包 @babel/preset-typescript:
{  "presets": [    "@babel/preset-typescript",    [      "@babel/preset-env"    ]  ],  "plugins": ["@babel/plugin-transform-runtime"]}
2. 单元测试文件的编写通过以上环节,jest 单元测试环境基本搭建完毕,接下来在__tests__下编写测试用例执行 yarn test

可以看到关于 debounce 防抖工具函数的测试情况显示在了控制台:

• stmts 是语句覆盖率(statement coverage):是不是每个语句都执行了?

• Branch 分支覆盖率(branch coverage):是不是每个 if 代码块都执行了?

• Funcs 函数覆盖率(function coverage):是不是每个函数都调用了?

• Lines 行覆盖率(line coverage):是不是每一行都执行了?

同时还会发现项目根目录多了一个 coverage 文件夹,里面就是 jest 生成的测试报告:3. 单元测试文件的编写引发的思考

每次修改单元测试都要执行 yarn test 去查看测试结果,怎么解决?

jest提供了 watch 指令,只需要配置 scripts 脚本就可以做到,单元测试的热更新。

"scripts": {  "test": "jest --watchAll"},

以后会写很多工具的测试用例,每次 test 都将所有工具都进行了测试,能否只测试自己写的工具?

jest 也提供了测试单个文件的方法,这样 jest 只会对防抖函数进行测试(前提全局安装了 jest)。

jest debounce.test.ts --watch
工具库包的发布

至此工具库距离开发者使用仅一步之遥,就是发布到npm上,发包前需要在 package.json 中声明库的一些入口,关键词等信息。

"main": "lib/main.js", // 告知引用该包模块化方式的默认文件路径  "module": "lib/main.esm.js", // 告知引用该包模块化方式的文件路径  "types": "lib/types/index.d.ts", // 告知引用该包的类型声明文件路径  "sideEffects": false, // false 为了告诉 webpack 我这个 npm 包里的所有文件代码都是没有副作用的  "files": [ // 开发者引用该包后node_modules包里面的文件    "lib",    "README.md"  ],  "keywords": [    "typescript",    "utils-demo",    "utils"  ],  "scripts": {    "pub": "npm publish"  },

登陆npm,你会看到自己的 packages 里面有了刚刚发布的工具库包:

写在最后

以上就是作者整理的从0到1构建基于自身业务的前端工具库的全过程,希望能给阅读本文的开发人员带来一些新的想法与尝试。

在此基础上已经成功在京东npm源发布了应用于京东汽车前端的工具库@jdcar/car-utils,并在各个业务线及系统得到落地。

当然,架构优化之路也还远未结束,比如:打包构建的速度、本地开发按需构建、工具库脚手架化等,后续我们也会基于自身业务以及一些新技术,持续深入优化,在性能上进一步提升,在功能上进一步丰富。本文或存在一些浅显不足之处,也欢迎大家评论指点。

参考资料

[1] rollup 英文文档(https://rollupjs.org/guide/en/#quick-start)

[2] rollup 中文文档(https://rollupjs.org/guide/zh/#introduction)

[3] Rollup.js 实战学习笔记(https://chenshenhai.github.io/rollupjs-note/)

[4] Rollup 打包工具的使用(https://juejin.cn/post/6844904058394771470)

[5] TypeScript、Rollup 搭建工具库(https://juejin.cn/post/6844904035309322254)

[6] 使用 rollup.js 封装各项目共用的工具包(https://juejin.cn/post/6993720790046736420)

[7] 如何开发一个基于 TypeScript 的工具库并自动生成文档(https://juejin.cn/post/6844903881030238221)

[8] 一款优雅、简洁的 JavaScript 测试框架(https://jestjs.io/zh-Hans/)

标签:

延伸阅读

推荐阅读

天天热资讯!从0到1构建基于自身业务的前端工具库

在实际项目开发中无论M端、PC端,或多或少都有一个utils文件目录去管理项目中用到的一些常用的工具方法,比如:时间处理、价格处理、解析url参

世界新动态:广州批发袜子最便宜的地方在哪里

袜子不仅可以保暖也可以说是穿搭中的一部分,而且袜子是高消耗品,不少人一次性都会买一大批袜子,对于新手商家来说想知道广州批发袜子最便宜

每日速讯:涟源:检察官为迷途知返的问题少年“撑起希望之伞”

近日,迷途知返的涉罪未成年人小亮(化名)因顺利通过检察机关为其设置的考察期,成功被大学本科录取,被涟源市人民检察院集中宣

台湾流行乐50年:冲出亚洲,退回小岛

当满头白发的老者在日月潭旁的山崖上抚琴低吟,而摄影棚内的舞台上成名于大陆的歌后也回以同样的旋律,两人隔空合歌的一幕击中了许多观众心中

今日报丨CFTC:大豆多空比升至7,COT指数继续呈现看多态度

一、基金净多单持仓与CBOT大豆价格基金净多单=非商业性多头持仓-非商业性空头持仓基金在市场中占据重要位置,基金净多单能很好揭示当前主力的

焦点播报:升降级办法确定,中超联赛重归升二降二

4月10日上午,中国足协、中足联筹备组在香河国家队足球训练基地组织召开了2023年中国足球职业联赛赛前工作会议。会上,协会与“筹备组”竞...

智能打印新赛道 奔图以体验赢得用户_全球新视野

随着国内外疫情政策放开,各地经济复苏提速,商业活动增加,商用办公打印需求回升,另外,居家远程办公、线上学习等办公学习方式改变了用户打

全球消息!部分影院不提供免费3D眼镜 涉嫌侵犯消费者权益

数据统计显示,今年清明档票房超过去年,全国电影市场回暖趋势持续。就在各地电影院迎来客流高峰的同时,一些观影者却发现,看3

法国高校春季教育展在大连举行_环球微头条

中新网大连4月9日电(记者杨毅)“我们法国见”法国高校春季教育展9日在辽宁大连举行,23所法国高校组团赴东北,并与近千名意向赴法留学生展...

环球今日报丨国企主导分拆上市潮 专精特新子公司成潜在标的

受访人士认为,国企成为“分拆”主力军,主要得益于政策的持续助推、分拆上市机制的不断完善,在建立中国特色估值体系、提升国有企业估值的...

【会员风采】东莞市众创联拓网络科技有限公司 今亮点

会员播报新入会企业介绍东莞市众创联拓网络科技有限公司东莞市众创联拓网络科技有限公司众创联拓成立于2015年(前身是东莞彩拓,2020年天使轮

万元现金失而复得,外籍乘客点赞广州公交

“非常感谢,感谢公交公司帮我找到钱包,同时也感谢司机快速的反应!”近日,广州市一汽巴士二分公司来了一名外籍乘客,用不太流

一会是指多久(一会儿是指多长时间啊!没有准确的时间长度来界定“等一下和等一)

一会是指多久一会是指多久一会表示的时间是一个模糊的概念,并没有具体的指代,有可能是五分钟,有可能是十五分钟等,但是通常用来指很短的时

世界简讯:顺义举办中医药文化节,近百名中医专家开展义诊

北京日报客户端|记者王可心4月9日,“潮白杏林展新颜,岐黄仁术传薪火”第五届顺义区中医药健康文化节开幕。在为期一周的时间里,多种中医...

当前观察:《典籍里的中国2》收官之作“对话”药王孙思邈!

4月9日(周日)晚八点档,《典籍里的中国》将在总台央视综合频道迎来第二季收官之作。继聚焦类书、地方史志、农学、地理学、茶学、文字学等诸多

海口四中高部羽毛球特长生考试视频|焦点快看

1、海口四中不错,从这几年中考成绩来看,在海口排名挺靠前的学校在初中里面还算是蛮大的,学校也还算有钱,给学生的活动经费很多,都几千几千

北京市宏庙小学学生参观雷锋精神主题展,听北京榜样讲述雷锋精神

“真没想到啊,原来雷锋叔叔的精神不只是搀扶别人过马路这么简单!这次的活动真是让我更加深入地理解了雷锋精神。”4月8日上午

送父亲的礼物排行榜

送父亲的礼物一定要根据父亲的喜好来选择礼物的,比如是手表、领带等等等都是合适的了,不用太贵,主要是你的心意,以及你的这份

今年快递业务量已超300亿件(新数据 新看点)

数据来源:国家邮政局  制图:汪哲平本报北京4月8日电(记者韩鑫)39天超100亿件,67天超200亿件,96天超300亿件!国家邮政局监测数据显示,

世界报道:什么信号?溢价90%,中东土豪A股抢筹!产业资本增持大潮再起,千亿回购为哪般?

什么信号?溢价90%,中东土豪A股抢筹!产业资本增持大潮再起,千亿回购为哪般?,a股,持股,股票,中东,上市公司,长江电力,徐工机械,产业资本,主

环球热讯:赶快升级!苹果发布iOS 16.4.1:修复各种大Bug

近日,苹果在不经意间推出了iOS16 4 1更新,内部版本号为20E252。这次更新主要是为了针对一些问题进行解决,同时还修复了两个已被黑客利用的安

茅草根的功效与作用图片_茅草根的功效与作用_快资讯

1、在农村有一种植物就是茅草根,小的时候经常去山间地头挖毛草根吃茅草根吃起来非常可口,那么农村的茅草根到底有什么功效呢?

二沙岛户外草坪响起民族交响乐,这场有“元宇宙”概念的音乐会连演3天

二沙岛户外草坪响起民族交响乐,这场有“元宇宙”概念的音乐会连演3天

“快旅慢游”成为时尚 “铁路+出游”助力旅游业强劲复苏

01:13央视网消息:4月7日上午10时多,载有600多名旅客的G4018次旅游专列从深圳北站驶出,开启了广西之旅。这是

安东尼:曼联的成绩要归功于滕哈赫,希望帮助曼联取得成功

安东尼:曼联的成绩要归功于滕哈赫,希望帮助曼联取得成功,曼联,欧冠,滕哈赫,卡塞米罗,马克·安东尼

中国气象局:未来十天冷空气频繁,9日起沙尘天气将卷土重来_天天报资讯

4月8日,澎湃新闻从中国气象局获悉,未来十天冷空气频繁,9日起沙尘天气将卷土重来。根据中央气象台预报,未来十天,我国冷空

江宁:法治赋能助力青少年“五育并举”

南京市江宁区依托青少年司法保护中心,聚焦落实立德树人根本任务,深入开展“4 8司法日”服务宣传活动,将法治元素同“德智体美劳”五育融...

每日视讯:半个韩娱参加李昇基李多寅婚礼,堪比黄晓明Angelababy世纪婚礼

虽然这几件电视台很少播韩剧了,但因为有了网络,很多韩国影视作品依然被中国观众追捧,一些韩星人气也不低,还有这些年韩国娱乐圈的八卦,可

射手座4月上半月发展,内心的消耗慢慢消失,呈现比较健康的状态

欢迎来到灵隐塔罗,那今天要和大家分享的是射手座在4月上半月的一个感情事业运势了。因为今天是一个大众占卜嘛,屏幕前的大家听取和自己相符相

光纤收发器套什么定额 世界快资讯

1、水晶头套综合布线里面的某项(具体的忘记了,需要看定额才能找到)。2、分光器没有用过建议套光纤收发器的,机箱也可以套综

猜您喜欢

    Copyright ©  2015-2022 现在服装网版权所有  备案号:粤ICP备18023326号-5   联系邮箱:855 729 8@qq.com