纵有疾风起
人生不言弃

vue cli4构建基于typescript的vue组件并发布到npm

基于vue cli创建一个vue项目

  首先安装最新的vue cli脚手架,

  npm install –global @vue/cli

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\@vue\cli\node_modules\fsevents):npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})+ @vue/cli@4.4.6added 1230 packages from 670 contributors in 118.122s

  查看安装的vue -V

@vue/cli 4.4.6

   创建项目:vue create my-project-name(“my-project-name”,这个可以根据需要命名,尽量用英文)

Vue CLI v4.4.6? Please pick a preset: Manually select features? Check the features needed for your project: Babel, TS, Router, Vuex, CSS Pre-processors, Linter? Use class-style component syntax? Yes? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes? Use history mode for router? (Requires proper server setup for index fallback in production) Yes? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (with node-sass)? Pick a linter / formatter config: Prettier? Pick additional lint features: Lint on save? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files? Save this as a preset for future projects? Yes? Save preset as: ts_tmpl

  创建完成之后,会出现如下提示

⚓  Running completion hooks...�  Generating README.md...�  Successfully created project my-project-name.�  Get started with the following commands: $ cd my-project-name $ npm run serve

  根据提示执行命令

E:\vue_codes>cd my-project-nameE:\vue_codes\my-project-name>npm run serve> my-project-name@0.1.0 serve E:\vue_codes\my-project-name> vue-cli-service serve INFO  Starting development server...Starting type checking service...Using 1 worker with 2048MB memory limit98% after emitting CopyPlugin DONE  Compiled successfully in 5304ms                                                                      上午11:13:54No type errors foundVersion: typescript 3.9.7Time: 3160ms  App running at:  - Local:   http://localhost:8080/  - Network: http://192.168.1.95:8080/  Note that the development build is not optimized.  To create a production build, run npm run build.

  在浏览器输入地址:http://localhost:8080/

vue cli4构建基于typescript的vue组件并发布到npm插图

  出现如上图所示界面,表示项目创建成功了。

   生成的代码目录结构如下:

vue cli4构建基于typescript的vue组件并发布到npm插图1

   两个声明文件:shims-vue.d.tsshims.tsx.d.ts

  shims-vue.d.ts由于 TypeScript 默认并不支持 *.vue 后缀的文件,所以在 vue 项目中引入的时候需要创建一个shims-vue.d.ts 文件,放在项目项目对应使用目录下,例如 src/shims-vue.d.ts,用来支持*.vue 后缀的文件

  shims-tsx.d.ts允许.tsx 结尾的文件,在 Vue 项目中编写 jsx 代码

  tsconfig.json:typescript配置文件,主要用于指定待编译的文件和定义编译选项

  normalize.css:Normalize.css 是一个可以定制的CSS文件,它让不同的浏览器在渲染网页元素的时候形式更统一。Normalize.css是一种CSS reset的替代方案。

  .browserslistrc:这个配置能够分享目标浏览器和nodejs版本在不同的前端工具。这些工具能根据目标浏览器自动来进行配置,Browserslist这个东西单独是没用的,(补充: 在vue官方脚手架中,browserslist字段会被 @babel/preset-env 和 Autoprefixer 用来确定需要转译的 JavaScript 特性和需要添加的 CSS 浏览器前缀。)

   browserslist的配置文件:
  > 1% 兼容全球使用率大于1%的游览器
  last 2 versions 兼容每个游览器的最近两个版本
  not ie <= 8 不兼容ie8及以下
  具体可见 browserslist。

  babel.config.js:Babel 是一个工具链,主要用于将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。

  postcss.config.js:用于配置将px转化成rem,和自动添加CSS浏览器前缀等。

  esnext 是一个 JavaScript 库,可以将 ES6 草案规范语法转成今天的 JavaScript 语法。

改造项目结构

  这种组件项目和我们日常的项目还是有很大区别的,由于前面我采用的是vue cli创建的完整模板项目,这里许多东西用不到,我们就将其删掉,最终项目目录结构如下:

vue cli4构建基于typescript的vue组件并发布到npm插图2

   examples:是组件使用示例

  src/components:是组件源码

  package.json代码如下:

{  "name": "jie-echarts",  "version": "0.1.0",  "private": false,  "description": "echarts组件",  "main": "dist/JieEcharts.common.js",  "author": "zouqj<zouyujie@126.com>",  "license": "MIT",  "scripts": {    "serve": "vue-cli-service serve",    "build": "vue-cli-service build",    "lint": "vue-cli-service lint",    "lib": "vue-cli-service build --target lib --name JieEcharts ./src/index.ts"  },
  “repository”: {
    “type”: “git”,
    “url”: “git+https://github.com/zouyujie/vue-components/tree/master/jie-echarts”
  },
  “bugs”: {
    “url”: “https://github.com/zouyujie/vue-components/issues”
  },
  “homepage”: “https://github.com/zouyujie/vue-components/tree/master/jie-echarts”,
  “keywords”: [
    “vue”,
    “vuejs”,
    “typescript”,
    “vuecli4.x”
  ],
  "dependencies": {    "core-js": "^3.6.5",    "echarts": "^4.8.0",    "ts-loader": "^8.0.1",    "vue": "^2.6.11",    "vue-class-component": "^7.2.3",    "vue-property-decorator": "^8.4.2",    "vue-router": "^3.2.0",    "vuex": "^3.4.0"  },  "devDependencies": {    "@types/echarts": "^4.6.4",    "@typescript-eslint/eslint-plugin": "^2.33.0",    "@typescript-eslint/parser": "^2.33.0",    "@vue/cli-plugin-babel": "~4.4.0",    "@vue/cli-plugin-eslint": "~4.4.0",    "@vue/cli-plugin-router": "~4.4.0",    "@vue/cli-plugin-typescript": "~4.4.0",    "@vue/cli-plugin-vuex": "~4.4.0",    "@vue/cli-service": "~4.4.0",    "@vue/eslint-config-prettier": "^6.0.0",    "@vue/eslint-config-typescript": "^5.0.2",    "eslint": "^6.7.2",    "eslint-plugin-prettier": "^3.1.3",    "eslint-plugin-vue": "^6.2.2",    "node-sass": "^4.12.0",    "prettier": "^1.19.1",    "sass-loader": "^8.0.2",    "typescript": "~3.9.3",    "vue-template-compiler": "^2.6.11"  }}

  重点注意标红部分的配置。

  tsconfig.json

{  "compilerOptions": {    "target": "esnext",    "module": "esnext",    "strict": true,    "jsx": "preserve",    "importHelpers": true,    "moduleResolution": "node",    "experimentalDecorators": true,    "esModuleInterop": true,    "allowSyntheticDefaultImports": true,    "sourceMap": true,    "baseUrl": ".",    "typeRoots": ["/@types", "./node_modules/@types"],    "types": ["webpack-env"],    "paths": {      "@/*": ["src/*"]    },    "lib": ["esnext", "dom", "dom.iterable", "scripthost"]  },  "include": [    "src/**/*.ts",    "src/**/*.tsx",    "src/**/*.vue",    "tests/**/*.ts",    "tests/**/*.tsx"  ],  "exclude": ["node_modules"]}

  vue.config.js代码如下:

'use strict';// Template version: 1.3.1// see http://vuejs-templates.github.io/webpack for documentation.const UglifyJsPlugin = require('uglifyjs-webpack-plugin');const webpack = require('webpack');const path = require('path');const resolve = (dir) => path.resolve(__dirname, dir);module.exports = {  // 修改 src 目录 为 examples 目录  pages: {    index: {      entry: 'examples/main.ts',      template: 'public/index.html',      filename: 'index.html',    },  },  // vue 通过 file-loader 用版本哈希值和正确的公共基础路径来决定最终的图片路径,再用 url-loader 将小于 4kb 的  // 图片内联,以减少 HTTP 请求的数量。所以我们可以通过 chainWebpack 调整图片的大小限制。例如,我们将  // 图片大小限制设置为 13kb,低于13kb的图片全部被内联,高于13kb的图片会放在单独的img文件夹中。  chainWebpack: (config) => {    const imagesRule = config.module.rule('images');    imagesRule      .use('url-loader')      .loader('url-loader')      .tap((options) => Object.assign(options, { limit: 13312 }));  },  // 设置css: { extract: false },可以强制内联,就不会将css单独打包成一个文件,导致页面没有style  css: { extract: false },  productionSourceMap: false,};

  说明:UglifyJS Webpack Plugin插件用来缩小(压缩优化)js文件,修改应用入口文件,examples/main.ts,方便执行npm run serve的时候,可以直接查看组件的示例。

 .npmignore可以将一些不需要发布到npm的文件忽略掉,.npmignore配置如下:

.*package-lock.json/.git//.vscode/tslint.jsontsconfig.json*.log.DS_Store/dist/examples/node_modules/public/src/tests.browserslistrcjest.config.jsvue.config.js# local env files.env.local.env.*.local# Log filesnpm-debug.log*yarn-debug.log*yarn-error.log*# Editor directories and files.idea.vscode.gitignore.npmignore.npmrc*.suo*.ntvs**.njsproj*.sln*.sw?

  components下面

  index.ts代码,以插件的形式进行封装,方便全局引用:

import jieEcharts from './jie-echarts.vue';(jieEcharts as any).install = (Vue: any) => {  Vue.component(jieEcharts.name, jieEcharts);};export default jieEcharts;

  jie-echarts.vue,是组件源码,代码:

<template>  <!-- 每一个图表都有自己唯一的id,需要动态传入。 -->  <div :ref="id" :id="id" :class="myclass" :style="style" /></template><script lang="ts">import { Component, Vue, Prop, Watch } from "vue-property-decorator";import Echarts from "echarts";@Component({  name: "jie-echarts"})export default class extends Vue {  @Prop({ default: "myCharts" }) private id!: string;  @Prop({ default: "100%" }) private width!: string;  @Prop({ default: "200px" }) private height!: string;  @Prop({ default: "echarts-line" }) private myclass!: string;  @Prop() private options!: object;  @Prop({ default: false }) private loading!: boolean;  private MyEcharts: any = null; // echarts实例  created() {    console.log("this.options :>> ", this.options);  }  mounted() {    this.InitCharts();  }  get style() {    return {      height: this.height,      width: this.width    };  }  @Watch("options", { deep: true })  onChangeOption(newVal: string, oldVal: string) {    if (this.MyEcharts) {      if (newVal) {        // console.log(JSON.stringify(newVal))        this.MyEcharts.setOption(newVal, true);      } else {        this.MyEcharts.setOption(oldVal, true);      }      setTimeout(() => {        this.MyEcharts.resize();      });    } else {      this.InitCharts();    }  }  @Watch("height")  onChangeHeight(val: string) {    if (val) {      this.height = val;    }    if (this.MyEcharts) {      this.MyEcharts.setOption(this.options, true);    } else {      this.InitCharts();    }  }  @Watch("loading")  onChangeLoading(val: boolean) {    if (val == true) {      this.showLoading();    }    if (val == false) {      this.hideLoading();    }  }  //-----------------------method----------------------  // 组件初始化  private InitCharts() {    const dom: any = this.$refs[this.id] as HTMLDivElement; // document.getElementById(this.id);    this.MyEcharts = Echarts.init(dom);    if (this.loading == true) {      this.showLoading();    }    /**     * 此方法适用于所有项目的图表,但是每个配置都需要在父组件传进来,相当于每个图表的配置都需要写一遍,不是特别的省代码,主要是灵活度高     * echarts的配置项,你可以直接在外边配置好,直接扔进来一个this.option     */    this.MyEcharts.clear(); // 适用于大数据量的切换时图表绘制错误,先清空在重绘    this.MyEcharts.setOption(this.options, true); // 设置为true可以是图表切换数据时重新渲染    setTimeout(() => {      this.MyEcharts.resize();    });    // 当窗口变化时随浏览器大小而改变    window.addEventListener("resize", () => {      this.MyEcharts.resize();    });    this.MyEcharts.on("click", (params: any) => {      this.mapClick(params);    });  }  //组件单击事件  private mapClick(params: any) {    // console.log(params, 999999);    const data = {      color: params.color,      data: params.data,      dataIndex: params.dataIndex,      seriesIndex: params.seriesIndex,      chartType: params.componentSubType    };    this.$parent.$emit("chartParams", JSON.stringify(data));    if (params.seriesType == "map") {      this.$emit("mapValue", params.name);    }       this.$emit("eclick", params);  }  private showLoading() {    if (this.MyEcharts) {      this.MyEcharts.showLoading({        text: "loading"        // color: '#4cbbff',        // textColor: '#4cbbff',      });    }  }  private hideLoading() {    if (this.MyEcharts) {      this.MyEcharts.hideLoading();    }  }
  beforeDestroy() {
    window.removeEventListener("resize", () => {
      this.MyEcharts.resize();
    });
  }}</script><style lang="scss" scoped>.echarts-line { height: 100%;}</style>

  @types目录下:

  component.d.ts代码:

import Vue from 'vue';export class VanComponent {  static name: string;  static install(vue: typeof Vue): void;}

  说明:@types是npm的一个分支,当我们把npm包发上去,npm包就会托管到服务器,供大家下载,但是ts为了代码的可复用性,要申明一些静态类型文件,那些文件就是*.d.ts

  shims-vue.d.ts代码:

declare module "*.vue" {  import Vue from "vue";  export default Vue;}

  App.vue,组件引入演示界面,代码:

<template>  <div id="app">    <jie-echarts :options="echartsOptions"></jie-echarts>  </div></template><script lang="ts">import { Component, Vue, Watch, Prop } from "vue-property-decorator";import jieEcharts from "../src/index";@Component({  components: {    jieEcharts  }})export default class TestJieEchartsPreview extends Vue {  protected echartsOptions = {    xAxis: {      type: "category",      data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]    },    yAxis: {      type: "value"    },    series: [      {        data: [820, 932, 901, 934, 1290, 1330, 1320],        type: "line"      }    ]  };}</script><style lang="scss">#app {  font-family: Avenir, Helvetica, Arial, sans-serif;  -webkit-font-smoothing: antialiased;  -moz-osx-font-smoothing: grayscale;  text-align: center;  color: #2c3e50;}#nav {  padding: 30px;  a {    font-weight: bold;    color: #2c3e50;    &.router-link-exact-active {      color: #42b983;    }  }}</style>

  执行npm run serve,运行结果如下:

vue cli4构建基于typescript的vue组件并发布到npm插图3

发布到NPM

  1.去https://www.npmjs.com/注册一个账号
  2.登录邮箱,点击激活连接
vue cli4构建基于typescript的vue组件并发布到npm插图4

  3.执行npm login,进行登录

PS E:\vue_codes\my-project-name> npm loginUsername: zouyujiePassword:Email: (this IS public) zouyujie@126.com

  如果你是使用的淘宝镜像,注意啊要先切换到npm官网镜像,切换方式:npm config set registry https://registry.npmjs.org/

  4.执行命令 npm publish,进行发布,如果出现如下图所示错误:

vue cli4构建基于typescript的vue组件并发布到npm插图5

   说明邮箱没有绑定成功,点击https://www.npmjs.com/email-edit,进行绑定,然后重新执行npm publish,运行结果如下:

PS E:\vue_codes\my-project-name> npm publishnpm notice npm notice package: jie-echarts@0.1.0npm notice === Tarball Contents ===npm notice 632B    dist/index.htmlnpm notice 4.3kB   dist/favicon.iconpm notice 66B     babel.config.jsnpm notice 965.0kB dist/js/chunk-vendors.80f39f1d.jsnpm notice 6.3kB   dist/js/index.f9222971.jsnpm notice 1.4kB   package.jsonnpm notice 327B    README.mdnpm notice === Tarball Details ===npm notice name:          jie-echartsnpm notice version:       0.1.0npm notice package size:  341.3 kBnpm notice unpacked size: 978.0 kBnpm notice shasum:        2b65bfa887ba4677dc95a36a4b0403ebfecc9fdenpm notice integrity:     sha512-RwSE3lC8N3wZT[...]b1b9cvJ8UtL/w==npm notice total files:   7npm notice+ jie-echarts@0.1.0

  至此,npm发布成功。

  然后我们去npm上,查看我们发布的npm包,

vue cli4构建基于typescript的vue组件并发布到npm插图6

   如果能看到如下图所示界面:

vue cli4构建基于typescript的vue组件并发布到npm插图7

   说明已发布成功。

  注意:每次重新发布都要记得修改一下版本号,否则会发布失败。发布成功后,你的npm邮箱都会受到一封npm组件发布成功的邮件通知。

  npm上地址:https://www.npmjs.com/package/jie-echarts

安装jie-echarts

     npm i jie-echarts

文章转载于:https://www.cnblogs.com/jiekzou/p/13424352.html

原著是一个有趣的人,若有侵权,请通知删除

未经允许不得转载:起风网 » vue cli4构建基于typescript的vue组件并发布到npm
分享到: 生成海报

评论 抢沙发

评论前必须登录!

立即登录