乐趣区

关于前端:从0到1搭建自己的组件vuecodeview库上

0x00 前言

本文将从构造、性能等方面解说下我的项目 vue-code-view 的搭建过程,您能够理解以下内容:

  • 应用 vue cli 4从 0 搭建一个组件库及粗疏配置信息。
  • 我的项目的多环境构建配置。
  • 我的项目网站的公布部署、继续集成。
  • 我的项目 NPM 包公布。
  • 我的项目组件的自定义 Markdown 解析 loader

本文算是 📚Element 2 源码学习系列 的拓展篇内容,通过之前的文章理解了开源组件库的构造原理后,本人也搭建个组件我的项目怎么办?接下来就是实际的过程,算是 ”知行合一“ 了吧!急躁读完,置信会对您有所帮忙!


0x01 我的项目概述

创立我的项目

本我的项目应用 Vue CLI 4.x 进行我的项目创立。

// 装置环境 
npm install -g @vue/cli 
// 创立我的项目 
vue create vue-code-view

在终端中输出命令后,依照以下步骤操作创立我的项目:

  1. 抉择手动抉择性能 Manually select features
  2. 选中 Babel, Router, CSS Pre-processors,Linter / Formatter等性能。
  3. 抉择 vue 版本 2.X
  4. 抉择路由是否应用 history 模式,默认 yes
  5. 抉择 CSS 预处理器Sass/SCSS(with node-sass)
  6. 抉择代码格调、格局校验 linter / formatter 配置ESLint + Prettier
  7. 抉择校验机会保留时检测Lint on save
  8. 抉择 Babel, ESLint等配置文件寄存在专用配置文件中 In dedicated config files

配置多环境变量

在我的项目根目录中新建 .env, .env.deploy,.env.production等文件。

VUE_APP 结尾的变量会被 webpack.DefinePlugin 动态嵌入到客户端侧的包中,代码中能够通过 process.env.VUE_APP[xxx] 拜访。

NODE_ENVBASE_URL 是两个非凡变量,在代码中始终可用。

.env\
vue-cli-service serve 默认的本地开发环境配置

NODE_ENV = development
VUE_APP_PUBLIC_PATH = /

.env.production\
vue-cli-service build 默认的环境配置(正式服务器)

NODE_ENV = production 
VUE_APP_PUBLIC_PATH = /
VUE_APP_ENV = pub

.env.deploy\
用于 github pages 构建部署的环境配置。VUE_APP_PUBLIC_PATH 设置 /vue-code-view 用于虚拟目录。

NODE_ENV = production 
VUE_APP_PUBLIC_PATH = /vue-code-view
VUE_APP_ENV = deploy

目录结构调整

默认的 src 目录下寄存我的项目源码及须要援用的资源文件。根目录下新建 examples 文件夹用于我的项目示例网站,将src 目录下文件移至 examples 文件。src 目录寄存我的项目组件源码。

调整后根目录文件构造如下:

├── examples   // 我的项目示例网站
|  ├── App.vue
|  ├── assets
|  ├── components
|  ├── main.js
|  ├── router
|  └── views 
├── src       // 我的项目组件源码 
|  ├── fonts
|  ├── index.js
|  ├── locale
|  ├── mixins
|  ├── src
|  ├── styles
|  └── utils
├── public
├── package.json

配置根底 vue.config.js

我的项目默认入口./src/main.js, 配置如下:

{
  entry: {
    app: ['./src/main.js']
  }
} 

在根目录下创立 vue.config.js 批改默认配置。

const path = require("path");
const resolve = (dir) => path.join(__dirname, dir);

module.exports = {configureWebpack: (config) => {
    // 我的项目入口
    config.entry.app = "./examples/main.js";
  },
  chainWebpack: (config) => {
    // 增加别名
    config.resolve.alias
      .set("vue$", "vue/dist/vue.esm.js")
      .set("@", resolve("examples"))
      .set("@assets", resolve("examples/assets"))
      .set("@src", resolve("src"))
      .set("@views", resolve("examples/views"))
      .set("@router", resolve("examples/router"))
      .set("@store", resolve("examples/store")); 
  },
}; 

运行 npm run serve,我的项目网站失常运行。

0x02 我的项目构建

npm scripts 配置

调整 package.json 里的 scripts 配置脚本, 并增加 --mode xxx 来抉择不同环境配置。

"scripts": { 
  // 开发环境 启动我的项目示例网站
  "dev": "vue-cli-service serve", 
  // 组件库构建 
  "dist": "vue-cli-service build  --mode production --target lib --name vue-code-viewer --dest lib src/index.js",
  // 我的项目示例网站构建
  "deploy:build": "vue-cli-service build --mode deploy" 
}

组件构建

组件库构建通过指定入口文件src/index.js、设定参数选项。

用法:vue-cli-service build [options] [entry|pattern]

参数选项:--mode        指定环境模式 (默认值:production)
  --dest        指定输入目录 (默认值:dist) 
  --target      app | lib | wc | wc-async (默认值:app)
  --name        库或 Web Components 模式下的名字 (默认值:package.json 中的 "name" 字段或入口文件名) 

构建一个库会输入:

  • lib/vue-code-viewer.common.js:一个给打包器用的 CommonJS 包。
  • lib/vue-code-viewer.umd.js:一个间接给浏览器或 AMD loader 应用的 UMD 包。
  • lib/vue-code-viewer.umd.min.js:压缩后的 UMD 构建版本。
  • lib/vue-code-viewer.css:提取进去的 CSS 文件。

组件 NPM 包公布

配置 package.json 文件中属性值用于 npm 公布。

  • name: 包名,该名字是惟一的。须要去 npm registry 查看名字是否已被应用。
  • version: 包版本号,版本号规定参考《语义化版本 2.0.0》。每次公布至 npm 须要批改版本号,不能和历史版本号雷同。
  • description: 包的形容,形容这个包的次要性能以及用处。
  • main: 入口文件,该字段需指向我的项目编译后的包文件。
  • unpkg: UMD 模式入口包文件
  • keyword:关键字,数组、字符串。
  • author:包的作者。
  • private:是否公有,须要批改为 false 能力公布到 npm
  • license:开源协定。
  • repository:包的 Git Repo 信息,包含 type 和 URL。
  • homepage:我的项目官网的 url。

更新 package.json 文件内容:

{
  "name": "vue-code-view",
  "version": "0.3.9",
  "description": "A code editor component based on Vue.js 2",
  "main": "lib/vue-code-viewer.common.js",
  "unpkg": "lib/vue-code-viewer.umd.js",
  "scripts": {},
  "dependencies": {},
  "peerDependencies": {},
  "devDependencies": {},
  "keywords": [
    "vue",
    "components",
    "codemirror",
    "code editor"
  ],
  "repository": {
    "type": "git",
    "url": "git+https://github.com/andurils/vue-code-view.git"
  },
  "author": "andurils",
  "license": "MIT",
  "homepage": "https://andurils.github.io/vue-code-view"
}

.npmignore 文件,设置疏忽公布文件。公布到 npm 中文件,只保留有的 lib 目录、package.json、README.md。

# 疏忽目录 
examples/
node_modules/
public/
build/
src/
dist/
deploy/
# 疏忽指定文件 
.browserslistrc 
.eslintignore 
.prettierignore 
.env
.env.*
*.js  

接下来 npmjs.com 上注册账号登录后,执行 npm publish 命令实现组件包公布操作。

公布胜利后,进入组件的 NPM 首页  npm/vue-code-view, 能够看到下面的我的项目配置信息。

我的项目示例网站构建

更新 vue.config.js,运行 npm run deploy:build 构建我的项目示例网站输入至 deploy 目录下。

const path = require("path"); 
const resolve = (dir) => path.join(__dirname, dir); 
const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV);

module.exports = { 
  publicPath: process.env.VUE_APP_PUBLIC_PATH || "/",
  productionSourceMap: false,
  outputDir: process.env.VUE_APP_ENV === "deploy" ? "deploy" : "dist",  
  configureWebpack: (config) => {
    // 我的项目入口
    config.entry.app = "./examples/main.js"
  },
  ...
};

继续集成

应用 Travis CI的继续集成服务主动构建我的项目示例网站并部署至 gh-pages 分支。

根目录下增加 .travis.yml文件,指定了 Travis 的行为。通过设置一旦代码仓库有新的 Commit,Travis 就会去找这个文件,执行外面的命令(执行构建、部署等操作)。
y

sudo: false
language: node_js
node_js: 14
install:
  - yarn 

script: npm run deploy:build
after_script: 
  - mkdir temp_web 
  - cd temp_web
  - git clone --depth 1 -b gh-pages --single-branch https://${TravisCI_Token}@${GH_REF} && cd vue-code-view 
  - echo 'copy && commit' 
  - rm -rf js fonts
  - cp -rf ../../deploy/** .
  - git config user.name "${U_NAME}"
  - git config user.email "${U_EMAIL}"
  - git add -A .
  - git commit -m ":construction_worker:- Build & Deploy by Travis CI"
  - git push origin gh-pages  
  - echo "DONE, Bye~"
  - exit 0

Travis CI我的项目构建后盾:

开启构建压缩

装置相干插件。

# gzip webpack 4.x 对应 6.x 版本 
npm i compression-webpack-plugin@6.1.1 -D 

# 代码压缩
npm i uglifyjs-webpack-plugin -D

配置 vue.config.js,开启插件。

...
const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV); 
// gzip 压缩  webpack 4.x 对应 6.x 版本 cnpm i compression-webpack-plugin@6.1.1 --save-dev
const CompressionWebpackPlugin = require("compression-webpack-plugin");
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;
// 代码压缩
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");

module.exports = { 
  ...
  configureWebpack: (config) => {const plugins = []; 
    // 生产环境相干配置
    if (IS_PROD && process.env.VUE_APP_ENV === "pub") {
      plugins.push(
        new CompressionWebpackPlugin({filename: "[path][base].gz",
          algorithm: "gzip",
          minRatio: 0.99,
          test: productionGzipExtensions,
          deleteOriginalAssets: false,
        })
      );
      plugins.push(
        new UglifyJsPlugin({
          uglifyOptions: {
            // 删除正文
            output: {comments: false,},
            // 删除 console debugger
            compress: {
              drop_debugger: true,
              drop_console: true, // console
              pure_funcs: ["console.log"], // 移除 console
            },
            // 删除正告
            warnings: false,
          },
          sourceMap: false,
          parallel: true, // 应用多过程并行运行来进步构建速度。默认并发运行数:os.cpus().length - 1。})
      );
    }
    config.plugins = [...config.plugins, ...plugins];
  },  
};

组件阐明文档

参考 element 2 的实现,自定义 build/md-loderMarkdown 文件进行解析渲染,将 examples\docs\zh-CN\example.md 编译为 HTML。已在前文 04. 封装组件封装、编写阐明文档 中具体阐明, 不再过多赘述。

配置 vue.config.js,增加 .md 文档的自定义 Markdown Loader

module.exports = { 
  ...
  configureWebpack: (config) => {config.resolveLoader.modules = ["node_modules", "./build/"]; // 自定义 loader
  },
  chainWebpack: (config) => { 
    // Markdown Loader
    config.module
      .rule("md")
      .test(/\.md/)
      .use("vue-loader")
      .loader("vue-loader")
      .end()
      // 自定义 loader
      .use("md-loader")
      .loader("md-loader")
      .end();},
}; 

examples\router\index.js配置路由:

const routes = [  
  {
    path: "/md",
    name: "Markdown",
    component: (r) =>
      require.ensure([], () => r(require("../docs/zh-CN/example.md"))),
  },
];

0x03 结尾

本篇幅次要依照我的项目从简到繁的顺寻逐渐解说了各操作项及细节配置。下文将就组件实现原理具体解说。

未完待续~

退出移动版