vuecli2创建的组件库工程实现按需引入

目前最新的vuecli版本是3,而vuecli3与vuecli2都使用了相同的命令vue,所以vuecli2被覆盖了,如果要使用vuecli2的init命令创建工程,需要安装一个桥接工具:@vue/cli-init

工程地址

npm install -g @vue/cli-init
# `vue init` 的运行效果将会跟 `vue-cli@2.x` 相同
vue init webpack my-project

官方说明地址:创建一个项目

  1. 创建一个vuecli2项目
    vue init webpack demo-vuecli2-ui
    
    在创建项目的过程中,选项如下:
    • Vue build:选择只要运行时版本的,因为这里不需要编译模板字符串版本,读者可以根据需要自行配置,对本次按需引入打包配置无关;
    • 不需要vue-router
    • 不需要eslint
    • 不需要unit test
    • 不需要e2e test
    • 不要自动执行npm install,自行处理
      在这里插入图片描述
  2. 打开项目,执行npm install安装依赖
  3. 安装完之后,npm run dev启动,检查是否正常。
    在这里插入图片描述
    一切正常
  4. 这里组件库的名字为:demo-vuecli2-ui,现在开始写组件,这里只写两个组件:
    • pl-button
    • pl-input

      除了这两个组件之外,还需要有一个体积比较大的组件,不然到时候测试按需引入的时候,很难观察到只引入部分组件(比如只引入button)所带来的打包体积优化效果。这里这个体积比较大的组件,使用element-ui来替代,把element-ui当做一个组件看待
  5. 安装element-ui
    npm i element-ui -D
    
    这里为什么要-D-D--save-dev的缩写,-S--save的缩写,--save会将依赖添加到package.jsondependency列表中,如果是--save-dev,会将依赖添加到devDependency列表中。将组件打包,然后发布到npm仓库之后,用户可以通过npm i demo-vuecli2-ui --save安装依赖,这时候,用户安装的时候也会去下载element-ui,这个可以通过观察node_modules/demo-vuecli2-ui目录验证,这个目录下面也会有一个node_modules文件夹,其中就是demo-vuecli2-ui的dependency列表。实际上用户是不需要再次安装下载element-ui的,所以这里是-D
  6. 编写组件,根目录下创建components文件夹,目录结构:
    - components
        - button
            - index.js
            - pl-button.vue
        - ele
            - index.js
        - input
            - index.js
            - pl-input.vue
        - index.js
    
    文件内容:
    /*components/button/index.js*/
    import Button from './pl-button'
    Button.install = (Vue) => Vue.component(Button.name, Button);
    export default Button
    
    /*components/button/pl-button.vue*/
    <template>
      <div class="pl-button">
        pl-button
      </div>
    </template>
    
    <script>
      export default {
        name: "pl-button"
      }
    </script>
    
    <style lang="scss">
      .pl-button {
        background-color: maroon;
        color: white;
      }
    </style>
    
    /*components/ele/index.js*/
    import ELE from 'element-ui'
    import 'element-ui/lib/theme-chalk/index.css'
    
    export default {
      install(Vue) {
        Vue.use(ELE)
      },
    }
    
    /*components/input/index.js*/
    import Input from './pl-input'
    Input.install = (Vue) => Vue.component(Input.name, Input)
    export default Input
    
    /*components/input/pl-input.vue*/
    <template>
      <div class="pl-input">
        pl-input
      </div>
    </template>
    
    <script>
      export default {
        name: "pl-input"
      }
    </script>
    
    <style lang="scss">
      .pl-input {
        background-color: #42b983;
        color: white;
      }
    </style>
    
    
    这个是总的打包入口
    /*components/index.js*/
    import Button from './button'
    import Input from './input'
    import Ele from './ele'
    
    export default {
      install(Vue) {
        Vue.use(Button)
        Vue.use(Input)
        Vue.use(Ele)
      },
    }
    
    

    这样用户在全引入组件库`demo-vuecli2-ui`,因为element-ui的存在,打包的体积会非常大,而用户在按需引入button以及input的时候,因为没有element-ui,打包的体积会大大缩小;
  7. 修改webpack配置文件,配置好调试组件以及打包组件的相关配置
    • 修改src/main.js,全引入组件,用来调试组件:
      import Vue from 'vue'
      import App from './App'
      
      import DVU from 'demo-vuecli2-ui'
      Vue.use(DVU)
      
      Vue.config.productionTip = false
      
      /* eslint-disable no-new */
      new Vue({
        el: '#app',
        render: h => h(App)
      })
      
    • 修改src/app.vue,调试组件:
      <template>
        <div id="app">
          <img src="./assets/logo.png">
          <pl-button/>
          <pl-input/>
          <el-button>hello world</el-button>
          <el-input/>
        </div>
      </template>
      
      <script>
        export default {
          name: 'App',
          components: {}
        }
      </script>
      
      <style>
        #app {
          font-family: 'Avenir', Helvetica, Arial, sans-serif;
          -webkit-font-smoothing: antialiased;
          -moz-osx-font-smoothing: grayscale;
          text-align: center;
          color: #2c3e50;
          margin-top: 60px;
        }
      </style>
      
    • 修改config/index.js,设置打包的输出文件夹为lib,同时js,css等资源文件输出路径由原来的lib/static改为lib。
      • 修改build.assetsRoot为:path.resolve(__dirname, '../lib'),
      • 修改build.assetsSubDirectory为:’’,就是一个空的字符串;
    • 修改package.json
      • 删除"private":true
      • 添加"main":“lib/index.js”
      • 添加"files":[“lib”]
    • 修改build/utils.js
      • 在底部添加以下方法,用来扫描组件入口信息
        const fs = require('fs')
        const join = path.join
        const resolve = (dir) => path.join(__dirname, '../', dir)
        
        exports.getComponentEntries = (path) => {
          let files = fs.readdirSync(resolve(path));
          const componentEntries = files.reduce((ret, item) => {
            const itemPath = join(path, item)
            const isDir = fs.statSync(itemPath).isDirectory();
            if (isDir) {
              ret[item] = resolve(join(itemPath, 'index.js'))
            } else {
              const [name] = item.split('.')
              ret[name] = resolve(`${itemPath}`)
            }
            return ret
          }, {})
          console.dir(componentEntries)
          return componentEntries
        }
        
    • 修改build/webpack.base.conf.js
      • 删除module.exports.entry,里面应该只有一个app入口;
      • resolve.alias添加一个:
        'demo-vuecli2-ui': resolve('components/index.js'),  
        
    • 修改build/webapck.dev.conf.js
      • module.exports中添加app入口,因为现在打包组件不需要打包页面了,只有调试组件的时候才需要这个入口,所以这里将这个app入口从webpack.base.conf.js中移到webpack.dev.conf.js:
        entry: {
            app: './src/main.js'
        },
        
    • 修改build/webapck.prod.conf.js
      • module.exports添加入口:
          entry: {
            ...utils.getComponentEntries('components')
          },
        
      • module.exports.output改为:
        path: config.build.assetsRoot,
        filename: utils.assetsPath('[name].js'),
        libraryTarget: 'commonjs2',
        libraryExport: 'default',
        library: 'demo-vuecli2-ui',
        
      • ExtractTextPlugin中的filename配置为:
        filename: utils.assetsPath('css/[name].css'),
        
      • 删除new HtmlWebpackPlugin(打包组件不需要页面)
      • 删除所有的new webpack.optimize.CommonsChunkPlugin(打包组件的时候不需要抽离公共的部分,否则在按需引入组件的时候,还得引入一些chunk-vendor以及chunk-common等js文件)
      • 删除new CopyWebpackPlugin(不需要将static目录拷贝到组件打包的目录)
  8. 修改完毕,启动本地调试,查看效果:
    [外链图片转存失败(img-7SXw0i3o-1566801706630)(2C1E88BA4B30409B83BE99C88680ED60)]
    自定义的pl-button、pl-input以及element-ui的组件都显示正常;
  9. 打包:npm run build,打包结果:
    [外链图片转存失败(img-VB3toVYn-1566801706631)(B5A3BE94EEDD4318AC3A79340AD47E99)]
  10. 发布到npm中,没有npm账号的同学,请自行注册账号以及在本地设备终端中登录;修改package.json文件中的版本号为0.0.1,然后发布:
    npm publish
    
    发布结果:
    [外链图片转存失败(img-Cf5Z0qPv-1566801706632)(514865F4021444F6AE4E5D48B07B8E35)]
    看到这个+ demo-vuecli2-ui@0.0.1表示发布成功。
  11. 接下来使用上一篇文章创建的test-load-on-demand工程测试按需引入是否配置成功。
    • 打开test-load-on-demand工程,安装demo-vuecli2-ui
      npm i vuecli2-ui@0.0.1 -S
      
    • 修改.babelrc文件:
      {
        "presets": ["@vue/app", ["@babel/preset-env", { "modules": false }]],
        "plugins": [
          [
            "component",
            {
              "libraryName": "demo-vuecli2-ui",
              "style": true,
              "styleLibrary": {
                "base": false,
                "name": "css"
              }
            }
          ]
        ]
      }
      
    • 修改src/main.js,全引入demo-vuecli2-ui:
      import Vue from 'vue'
      import App from './App.vue'
      
      import DVU from 'demo-vuecli2-ui'
      import 'demo-vuecli2-ui/lib/css/index.css'
      Vue.use(DVU)
      
      
      Vue.config.productionTip = false
      new Vue({
          render: h => h(App),
      }).$mount('#app')
      
    • 修改App.vue,显示所有demo-vuecli2-ui的组件:
      <template>
        <div id="app">
          <img alt="Vue logo" src="./assets/logo.png">
          <pl-button/>
          <pl-input/>
          <el-button>hello world</el-button>
          <el-input/>
        </div>
      </template>
      
      <script>
      export default {
        name: 'app',
      }
      </script>
      
      <style lang="scss">
      </style>
      
    • 启动,检查效果:
      [外链图片转存失败(img-jR8vUC7X-1566801706632)(31AFDAE85A8741608BB24E32EBF27A9D)]
      可以看到,app.js文件大小为4.0m
    • 打包页面,在浏览器中打开index.html
      [外链图片转存失败(img-eXCgwGKN-1566801706632)(25EFA7EEA7734C93B70A9BC94FFFDD21)]
      可以看到,chunk-vendor文件大概800多k;
    • 配置为按需引入,src/main.js:
      import Vue from 'vue'
      import App from './App.vue'
      
      import {Button, Input} from 'demo-vuecli2-ui'
      Vue.use(Button)
      Vue.use(Input)
      
      Vue.config.productionTip = false
      new Vue({
          render: h => h(App),
      }).$mount('#app')
      
    • 启动,检查效果:
      [外链图片转存失败(img-xlWWJ5hF-1566801706632)(977BBE3D12DB432FB3BFDA3DAACDBA7A)]
      可以看到,app.js变为了1.8m
    • 打包,然后直接打开index.html,检查效果:
      [外链图片转存失败(img-vPFJkHpa-1566801706632)(0D9954A4B4EB4DAB8CA2A9E5E82155E2)]
      可以看到,chunk-vendor变成了80k大小
    • 至此,vuecli2工程组件库按需引入说明已经结束
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值