[vue]利用webpack同時打包提供npm和純html的方式,並且發佈到npm官方提供給人使用

  • 2934
  • 0
  • vue
  • 2018-02-20

介紹如何使用webpack來幫我們打包並發佈到npm官方,且整合github來做一個demo網頁,來提供說明文章和package供人使用

前言

最近因為有想要發佈一個簡單的component到npm,主要是數字方面的控制項,在之前和這次的專案都有遇到,即然做好了便想說透過npm來供人下載,而此篇則想記錄一下如何發佈到npm,並使用github來做一個靜態網頁,當做demo頁面給人可以實際操作,而當中因為需要打包所以我們需要用到webpack,就來看看整個過程是如何達成的吧。

  1. 使用npm建立一個專案
  2. 使用webpack做一個demo頁面
  3. 打包node和傳統網頁都能使用的元件
  4. 安裝eslint來提升開發品質
  5. 發佈npm供人使用
  6. 用github做一個靜態網頁,提供demo供人使用
  7. 結論

使用npm建立一個專案

首先建立一個資料夾,然後使用npm init來建立一個package.json,過程會詢問一些問題,筆者把說明貼在下方,而關於git位置的部份,基本上只要在cli建立的時候,你有提供訊息,預設就會幫你填好了。

{
  "name": "vue-txt-number", // npm供人下載的名稱,npm i test
  "version": "1.0.0", // npm發佈的版本,每次要發佈必定得改版號
  "description": "", // 說明
  "main": "dist/vue-txt-number.js", //import test from 'test'時會參考的預設檔案
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/kinanson/vue-txt-number.git"
  },
  "keywords": [
    "vue",
    "vue number",
    "vue limit decimal length",
    "javascript"
  ],
  "author": "kinanson",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/kinanson/vue-txt-number/issues"
  },
  "homepage": "https://github.com/kinanson/vue-txt-number#readme",
}

使用webpack做一個demo頁面

因為我希望打開原始碼的時候,可以有一個測試頁面,供我開發使用,所以包括babel等等我都得安裝,有時候我想改別人原始碼的時候,卻發現對方根本沒有提供開發環境,就會讓我覺得很困擾,所以適時的提供現成的開發頁面,或許會幫助更多開發者來對你的package pull request哦,接下來就說明一下如何開始吧,先安裝必要的package

npm i babel-core babel-loader  babel-plugin-transform-runtime babel-preset-env babel-preset-stage-2 cross-env css-loader node-sass npm-run-all sass-loader style-loader vue-loader  vue-style-loader vue-template-compiler webpack webpack-dev-server --D

有些package視需要安裝,比如說sass筆者是全部都安裝比較省事了,npm-run-all則是為了讓windows平台可以同時執行兩個npm用的,接著新增專案必要的檔案,首先在根目錄新增.babelrc

{
  "presets": [
    ["env", { "modules": false }],
    "stage-2"
  ],
  "plugins": ["transform-runtime"]
}

接著在根目錄新增一支index.html,主要是當我們本地開發的時候能直接跑起來測試

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app"></div>
  <script src="dist/app.js"></script>
</body>
</html>

接著來做一個最基本的webpack配置吧,如果你對webpack不熟或很陌生的話,可以參考筆者以前寫的文章(https://dotblogs.com.tw/kinanson/2017/06/11/124206),webpack3跟webpack2基本上都是共用的。

const path = require('path'),
  webpack = require('webpack')

let webpackConfig = {
  entry: {
    app: './src/index.js'
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname + '/dist')
  },
  resolve: {
    extensions: ['.vue', '.js']
  },
  devtool: '#cheap-module-eval-source-map',
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [path.join(__dirname, 'src'), path.join(__dirname, 'demo')],
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      },
      {
        test: /\.scss$/,
        use: ["style-loader", "css-loader", "sass-loader"]
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }
    ]
  }
}

module.exports = webpackConfig

接著改一下pakcage.json的scripts部份,因為我新增可以監控並同時跑起一個網站,所以我想要用一個命令同時執行兩個動作,所以我用start同時去執行watch和dev

"watch": "cross-env NODE_ENV=dev webpack --watch ",
"dev": "cross-env NODE_ENV=dev webpack-dev-server",
"start": "npm-run-all --parallel dev watch"

然後就可以直接執行npm start,來開始偵錯了,那src資料夾裡面的部份呢?首先新增src/index.js

import Vue from 'vue'
import Demo from './demo.vue'

new Vue({
  el: '#app',
  render: h => h(Demo),
  template: '<Demo/>',
  components: {
    Demo
  }
})

這支主要是在開發時候用的,接著看一下Demo.vue的部份,就是直接去使用component來做測試

<template>
  <div>
    <vue-txt-number v-model="number"></vue-txt-number>
  </div>
</template>

<script>
import VueTxtNumber from './components/vue-txt-number.vue'
export default {
  components: {
    VueTxtNumber
  },
  data () {
    return {
      number: 3
    }
  }
}
</script>

<style>
</style>

最後再來看一下src/build.js的部份,主要就是當我們要打包發佈到npm時候會產生的js

import VueTxtNumber from './components/vue-txt-number'

const install = (Vue, opts = {}) => {
  Vue.component(VueTxtNumber.name, VueTxtNumber)
}

if (typeof window !== 'undefined' && window.Vue) {
  install(window.Vue)
}

export default { VueTxtNumber, install }

打包node和傳統網頁都能使用的元件

開發vue的人都知道彈性很大,可以掛戴一支vue.js就開始用vue來binding,或者另一種就是用cli來產生環境生態開發,偏偏很多開發元件的人,並未兩種都兼顧到,這邊先來討論一下如何打包node的元件,在npm的main我們已經有指定了一支js檔,那支就是給npm預設引用的,不過為了後續可以同時打包傳統方式也能用的元件,先來安裝一下webpack merge

npm i webpack-merge --D

接著因為我們想要在一次打包的時候,同時產生node和普通網頁都能使用的版本,所以我把webpack改成如下

const path = require('path'),
  webpack = require('webpack'),
  rimraf = require('rimraf'),
  merge = require('webpack-merge')

let webpackConfig = {
  entry: {
    app: './src/index.js'
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname + '/dist')
  },
  resolve: {
    extensions: ['.vue', '.js']
  },
  devtool: '#cheap-module-eval-source-map',
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [path.join(__dirname, 'src'), path.join(__dirname, 'demo')],
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      },
      {
        test: /\.scss$/,
        use: ["style-loader", "css-loader", "sass-loader"]
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }
    ]
  }
}

rimraf(path.join(__dirname, 'dist'), () => console.log('success remove'))

switch (process.env.NODE_ENV) {
  case 'dev':
    module.exports = webpackConfig
    break
  case 'prod':
    webpackConfig.devtool = "#source-map"
    webpackConfig.externals = { //這邊指定打包時忽略vue的package,調用者必定都會安裝vue,所以我們不需要增加vue的體積
      vue: 'vue'
    }
    module.exports = [
      merge(webpackConfig, {
        entry: './src/components/vue-txt-number.vue', // 直接輸入vue檔,供node使用
        output: {
          filename: 'vue-txt-number.js',
          libraryTarget: 'umd',
          library: 'vue-txt-number', // import的名稱
          umdNamedDefine: true //會對umd購建過程做命名
        }
      }),
      merge(webpackConfig, {
        entry: path.resolve('./src/build.js'),
        output: {
          filename: 'vue-txt-number.min.js',
          libraryTarget: 'window', // 使用window變數
          library: 'VueTxtNumber', // 註冊在window全局變數,所以從window會取得VueTxtNumber,在傳統網頁直接就能使用
        }
      })
    ]
    break
}

接著改一下package.json,新增一個build的命令

"build": "cross-env NODE_ENV=prod webpack -p"

打包完成基本上就能看到dist有四支檔案了

vue-txt-number.min.js直接掛在src就能使用此元件囉,而vue-txt-number.js則是給node module使用的。

安裝eslint來提升開發品質

在開發的過程,還是希望會有檢查語法的工具,來幫助統一程式風格,所以接著就來安裝eslint吧,首先執行如下指令,安裝必要工具

npm i eslint eslint-config-standard eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-standard eslint-plugin-vue babel-eslint --D

接著在根目錄新增.babelrc然後加入以下的內容

{
  "presets": [
    ["env", { "modules": false }],
    "stage-2"
  ],
  "plugins": ["transform-runtime"]
}

然後是eslint的配置部份,新增.eslintrc.js

module.exports = {
  root: true,
  parserOptions: {
    parser: 'babel-eslint'
  },
  env: {
    browser: true,
  },
  extends: [
    'plugin:vue/essential',
    'standard'
  ],
  plugins: [
    'vue'
  ],
  rules: { 
    'arrow-parens': 0,
    'no-new': 0,
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
  }
}

這樣就可以完成了用eslint來檢查我們的程式碼

發佈npm供人使用

這邊只講npm,就不談github了,基本上能走到這步我相信對github的基本操作應該都不會是很大的問題了,如果我們想要發佈npm的話,第一件事情就是到官方申請一下帳號(https://www.npmjs.com/signup),

註冊成功之後,進到首頁可以看到自己的npm package,像筆者目前只有一個非常不完善的元件

如果你想要打包的話,請先至專案的底下,使用cli輸入如下指令

npm adduser

接著會要你輸入帳號和密碼


完成後只要輸入如下指令就能發佈了

npm publish

特別得注意一下,如果你想要再次發佈的話,一定得要改掉package.json的version才能發佈,如果你要把發佈的專案移除掉的話,可以使用如下指令

npm unpublish

但官方非常不建議你移除掉,所以會產生如下錯誤訊息,提示你要使用--force的方式


需注意一下如果你移除掉的話,下次想要發佈就要用不同名稱或者不同版號囉,所以基本上如果有任何要測試就反覆改版號就對了,而不要用移除的方式來處理。

用github做一個靜態網頁,提供demo供人使用

這邊則是選擇性的,但是最好能提供,比方我在看別人提供的第三方元件的時候,通常都會先考慮可以直接使用看看,甚至可以測試的demo,如果沒有demo的話,如果有很多其他選擇的話,我可能就會想要去選擇其他的package,而在github可以做一個自己的靜態網頁,當然也可以是一個spa的網站,那首先了解一下我們如何做一個自己的github網站吧,首先建立一個repository為自己帳號並符合此規則的名稱

kinanson.github.io

建立完成之後,以筆者的例子,是直接使用vue官方的cli來實做一個spa的網站,當我打包的時候,把此打包的目錄push到repository,需要注意這邊不能使用html5的模式,否則會404哦,可以直接看筆者的github檔案(https://github.com/kinanson/kinanson.github.io)

當我們把靜態網站放上去之後,直接訪問(帳號.github.io),就可以看到你在github上面的靜態網頁了,當然如果你有很多的package或者作品想給人看,都可以使用這個資源來提供哦,而網址則是對應到我們的spa route設定,當然如果你是一支一支的html也是可行的,就看自己如何利用了。

結論

相信大家常常在使用別人提供的npm,有時候當我們覺得某種需求一直在出現,然後npm又沒有適合自己的元件,適時的出一份力提供給別人用,也是對開放原始碼出一份心力,如果更多元件可以使用,就會吸引更多人來用vue,有時候功能太強大的元件自己並用不到,並且使用起來挺複雜的,或許你設計的簡單元件剛好更符合某些使用者使用哦,如果想了解整個原始碼的話,可以直接去筆者的github察看。

https://github.com/kinanson/vue-txt-number