环境搭建-组件打包环境

组件打包环境 目前我的理解是,把要独立出来的组件 全部放到了一个固定的目录,和 开发测试环境分开了。

组件打包的目录如下:

| - rootxxx                 # 项目根目录(项目名)
    |- src                  # 用于组件开发,vue-li默认生成的目录
        |- components       # 我们所有的组件都放在这个里面 
          |- hello          # hello组件目录
            |-Hello.vue     
            |-index.js      # 模块化暴露文件

本次只配置组件打包和使用,其他的需求以后再慢慢深入了解

1. 编写第一个组件

src/components/hello/Hello.vue

<template>
  <div class="hello">
    <h1>{{ title }}</h1>
    <h3>{{ msg }}</h3>
    <ul>
      <li><a href="http://router.vuejs.org/" target="_blank">vue-router</a></li>
      <li><a href="http://vuex.vuejs.org/" target="_blank">vuex</a></li>
      <li><a href="http://vue-loader.vuejs.org/" target="_blank">vue-loader</a></li>
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank">awesome-vue</a></li>
    </ul>
  </div>
</template>

<script>
  export default {
    props: {
      title: String
    },
    data () {
      return {
        msg: 'hello word'
      }
    }
  }
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
  h1, h2 {
    font-weight: normal;
  }

  ul {
    list-style-type: none;
    padding: 0;
    background-color: #9ebdd7;
  }

  li {
    display: inline-block;
    margin: 0 10px;
  }

  a {
    color: #42b983;
  }
</style>

src/components/hello/index.js

import Hello from './Hello'
export default Hello

到此为止我们的组件写完了,测试怎么测试呢?

  • 直接和平时开发webapp一样,可以直接引入该vue文件。
  • 还可以使用 Vue.use(xx) 安装的方式来引入文件,这种方式下面讲

2. 实现Vue.use全局安装我们的组件

由于我们写的是组件库。所以要暴露很多不同的组件。需要一个统一的js来进行安装。

src/index.js

/**
 *
 * <pre>
 *  Version         Date            Author          Description
 * ---------------------------------------------------------------------------------------
 *  1.0.0           2017/07/25     zhuqiang        -
 * </pre>
 * @author zhuqiang
 * @version 1.0.0 2017/7/26 13:54
 * @date 2017/7/26 13:54
 * @since 1.0.0
 */
// 这个难道是一个es6的补丁?正常的vue-cli中已经包含了补丁了应该。所以这个暂时不知道去掉后怎么重现故障
import 'core-js/fn/array/find-index'

import Hello from './components/hello'
let VueComponentsLib = {
  Hello
}

const install = function (Vue, opts = {}) {
  Object.keys(VueComponentsLib).forEach((key) => {
    Vue.component(key, VueComponentsLib[key])
  })
}

// auto install
if (typeof window !== 'undefined' && window.Vue) {
  install(window.Vue)
}
// 把 install方法添加到 VueComponentsLib 中
export default Object.assign(VueComponentsLib, {install})
// module.exports = Object.assign(tlzVueElUi, {install})   // eslint-disable-line no-undef

这个测试方法如下:

在examples/main.js中添加如下代码

import VueComponentsLib from '../src/index'
Vue.use(VueComponentsLib)

好了,这个被全局安装了,至于按需安装的话,我就没有研究了,后台系统全局安装能满足我的需求了。

3. 打包成js

我看百度有直接把vue打包出去的。这个方法不知道有用没有,打包成js的话,说得最多的是,在非vue-cli环境下也能使用。或许在vue-cli环境下直接使用这里的 .vue文件的组件也是可以的把?

首先呢,同本地预览的思路差不多,我们先增加基础的配置

config/index.js

在以前的基础上增加一个配置环境,不过这里暂时还不知道需要哪些变量配置,因为直接打成js包和webapp包还不一样

  buildProdLib:{
    env: require('./prod.lib.env.js'),
  }

config/prod.lib.env.js

module.exports = {
  NODE_ENV: '"prodlib"'
}

基础参数配置好了,接下来还是从命令行入口处开始 package.json

  "scripts": {
    "build": "node build/build.js",
    // 同样模仿上面的默认配置来修改
    "build:prodLib": "node build/buildProdLib.js",

build/buildProdLib.js

复制了一份build/build.js来修改。 这个文件是启动构建并显示构建后的文件大小。就和原生构建web应用时的效果一样

require('./check-versions')()

// 这里的环境改成我们自己的
process.env.NODE_ENV = 'prodlib'

var ora = require('ora')
var rm = require('rimraf')    // 这个查了下,大概是清理文件的插件
var path = require('path')
var chalk = require('chalk')
var webpack = require('webpack')
var config = require('../config')
// 这里同理复制一份 webpack.prod.conf.js 修改成 webpack.prodLib.conf.js
var webpackConfig = require('./webpack.prodLib.conf')

var spinner = ora('building for production...')
spinner.start()

// 也就是说,这里帮我们清理了以下目录
// 然而这里我们只需要清空自己的打包目录就行了
// 之前在config/index.js中没有定义多的变量,在这里要用到了,需要添加上
//  assetsRoot: path.resolve(__dirname, '../lib'),
rm(path.join(config.buildProdLib.assetsRoot), err => {
  if (err) throw err
  webpack(webpackConfig, function (err, stats) {
    spinner.stop()
    if (err) throw err
    process.stdout.write(stats.toString({
      colors: true,
      modules: false,
      children: false,
      chunks: false,
      chunkModules: false
    }) + '\n\n')

    console.log(chalk.cyan('  Build complete.\n'))
    console.log(chalk.yellow(
      '  Tip: 构建的文件是js库的文件\n' +
      '  因此该库能被引用使用\n'
    ))
  })
})

build/webpack.prodLib.conf.js

var path = require('path')
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
// 下面这四个插件没有什么用了
var CopyWebpackPlugin = require('copy-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')

// 这里如果不是测试环境,就改成我们自己的打包环境
//  暂时这个测试的我还不会,但是看到开源框架都安装了这个unit测试
// 所以这里暂时不用理会其他的。环境变量先改成我们自己的就好
var env = process.env.NODE_ENV === 'testing'
  ? require('../config/test.env')
  : config.buildProdLib.env

// 该模块下由于咱们是打成js包,所以很多文件都不需要生成和处理
// 这里啰嗦一句,从配置本地预览开发环境和打包环境 都是覆盖了baseWebpackConfig中的入口和输出目录
// 所以建议直接把baseWebpackConfig中的entry和output移除
var webpackConfig = merge(baseWebpackConfig, {
  entry: {
    app: './src/index.js'
  },
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true
    })
  },
  // devtool: config.build.productionSourceMap ? '#source-map' : false,
  output: {
    path: config.buildProdLib.assetsRoot,
    // 再次增加一个变量目录
    publicPath: config.buildProdLib.assetsPublicPath,
    // 库文件名,同样我们需要把这两个都写到配置里面去
    filename: config.buildProdLib.filename,
    // 库名称
    library: config.buildProdLib.library,
    libraryTarget: 'umd',
    umdNamedDefine: true
  },
  // 增加一个配置,在iview中定义的,百度说是支持不同的加载方式
  externals: {
    vue: {
      root: 'Vue',
      commonjs: 'vue',
      commonjs2: 'vue',
      amd: 'vue'
    }
  },
  plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': env
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      },
      sourceMap: true
    }),
    // extract css into its own file
    // new ExtractTextPlugin({
    //   filename: utils.assetsPath('css/[name].[contenthash].css')
    // }),
    // Compress extracted CSS. We are using this plugin so that possible
    // duplicated CSS from different components can be deduped.
    // new OptimizeCSSPlugin({
    //   cssProcessorOptions: {
    //     safe: true
    //   }
    // }),
    // 这里的HtmlWebpackPlugin插件用不到了,直接删除掉了
    // 下面的插件也是用不到的了
    // split vendor js into its own file
    // new webpack.optimize.CommonsChunkPlugin({
    //   name: 'vendor',
    //   minChunks: function (module, count) {
    //     // any required modules inside node_modules are extracted to vendor
    //     return (
    //       module.resource &&
    //       /\.js$/.test(module.resource) &&
    //       module.resource.indexOf(
    //         path.join(__dirname, '../node_modules')
    //       ) === 0
    //     )
    //   }
    // }),
    // 这个配置应该是压缩js的
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      },
      sourceMap: false
    }),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
//     new webpack.optimize.CommonsChunkPlugin({
//       name: 'manifest',
//       chunks: ['vendor']
//     }),
// copy custom static assets
//     new CopyWebpackPlugin([
//       {
//         from: path.resolve(__dirname, '../static'),
//         to: config.build.assetsSubDirectory,
//         ignore: ['.*']
//       }
//     ])
  ]
})

// 这个压缩没有什么用了
// if (config.build.productionGzip) {
//   var CompressionWebpackPlugin = require('compression-webpack-plugin')
//
//   webpackConfig.plugins.push(
//     new CompressionWebpackPlugin({
//       asset: '[path].gz[query]',
//       algorithm: 'gzip',
//       test: new RegExp(
//         '\\.(' +
//         config.build.productionGzipExtensions.join('|') +
//         ')$'
//       ),
//       threshold: 10240,
//       minRatio: 0.8
//     })
//   )
// }
// npm run build:prodLib --report  显示构建报表
if (config.buildProdLib.bundleAnalyzerReport) {
  var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

文件就配置完成了,补充下在修改文件配置的时候增加的配置变量

config/index.js

打包环境的配置变量如下

  buildProdLib: {
    env: require('./prod.lib.env.js'),
    assetsRoot: path.resolve(__dirname, '../lib'),
    assetsPublicPath: '/lib/',
    filename:'vueComponentsLib.min.js',
    library:'vueComponentsLib',
    bundleAnalyzerReport: process.env.npm_config_report
  }

4. 打包测试

# 只打包
npm run build:prodLib
# 打包并查看报表
npm run build:prodLib --report

构建完成后生成lib/vueComponentsLib.min.js 文件

5. 使用打包后的js文件进行测试

在开发测试环境测试 examples/main.js

# 把直接引用的js替换成打包好的js
// import VueComponentsLib from '../src/index'
import VueComponentsLib from '../lib/vueComponentsLib.min.js'

最终成功;

然后有一个问题就是,我们写组件库的话,css怎么办?参考了各大开源框架,一般都不会把css写在vue组件里面,也不能使用scoped。因为方便使用者覆盖样式。

那么我们的接下来要做的就是,单独使用css文件样式,然后单独打包css文件。

下一章节:环境搭建-单独css打包配置

© All Rights Reserved            updated 2017-12-28 02:49:41

results matching ""

    No results matching ""