3

编译vue单文件组件

 3 years ago
source link: https://sobird.me/compile-vue-signle-file-component.htm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

编译vue单文件组件

分类:技术 | 9月 11th, 2018 | 2,700 views | 2 条评论

Vue官方定义了一种名叫单文件组件(SFC)规范的*.vue文件,用类 HTML 语法描述一个 Vue 组件。每个 .vue 文件包含三种类型的顶级语言块 <template><script><style>,还允许添加可选的自定义块:

<template>
  <div class="example">{{ msg }}</div>
</template>

<script>
export default {
  data () {
    return {
      msg: 'Hello world!'
    }
  }
}
</script>

<style>
.example {
  color: red;
}
</style>

<custom1>
  This could be e.g. documentation for the component.
</custom1>

为此Vue的官方提供了vue-loader,它会解析文件,提取每个语言块,如有必要会通过其它 loader 处理,最后将他们组装成一个 ES Module,它的默认导出是一个 Vue.js 组件选项的对象。

vue-loader 支持使用非默认语言,比如 CSS 预处理器,预编译的 HTML 模版语言,通过设置语言块的 lang 属性。例如,你可以像下面这样使用 Sass 语法编写样式:

<style lang="sass">
  /* write Sass! */
</style>

详情见https://vue-loader.vuejs.org/zh/

大部分情况下我们开发Vue项目是通过vue-cli这个脚手架快速生成一个项目骨架而开始的

vue init webpack my-vue-project

然后我们在这个项目中编写.vue单文件组件,通过:

npm rub build 

构建整个项目,将产出的文件发布上线,事实上在整个项目构建过程中我们并不知道.vue文件到底发生了什么。当然如果只是单纯通过这种方式来开发一个Vue的单页项目,其实也并不需要了解太多细节,我们只需要按照给定的项目规范编写业务代码即可,但这种傻瓜式的开发配置,有时候并不能满足多变的需求。

既然Vue官方已经定义了一种单文件组件(SFC)规范的东东,我们何不借来使用:实现组件的平台化。我们提供一个.vue组件编辑器供用户使用,编辑完成后单击保存,即可看到该组件渲染之后的页面。

在这个过程中会涉及到如何编译.vue单文件组件,以及动态/异步渲染vue单文件组件,本文主要记录编译vue单文件组件的几种方法:

在开始之前我们提前创建了一个项目:compile-vue-demo,方便您的调试和查看,该项目集成了下面几种编译方式。

rollup

Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。Rollup 对代码模块使用新的标准化格式,这些标准都包含在 JavaScript 的 ES6 版本中,而不是以前的特殊解决方案,如 CommonJS 和 AMD。ES6 模块可以使你自由、无缝地使用你最喜爱的 library 中那些最有用独立函数,而你的项目不必携带其他未使用的代码。ES6 模块最终还是要由浏览器原生实现,但当前 Rollup 可以使你提前体验。

// rollup.config.js
import VuePlugin from 'rollup-plugin-vue'

export default {
  entry: 'src/main.vue',
  format: 'iife',
  dest: 'rel/bundle.js',
  output: {
    name: 'main',
  },
  plugins: [VuePlugin(/* VuePluginOptions */)],
}

项目里的entry.rollup.html文件为rollup编译的入口文件,通过运行下面的命令编译:

rollup -c --watch

webpack

项目里的entry.webpack.html文件为webpack编译方式的入口文件,通过运行下面的命令来编译:

webpack
// webpack.config.js
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
  entry: './src/hello.vue',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, './dist'),
    library: 'hello',
    //libraryTarget: 'umd'
  },
  mode: 'development',
  devtool: 'none',
  module: {
    rules: [
      // 解析.vue文件
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      // 它会应用到普通的 `.css` 文件
      // 以及 `.vue` 文件中的 `<style>` 块
      {
        test: /\.css$/,
        loader: 'css-loader'
      },
      // 它会应用到普通的 `.js` 文件
      // 以及 `.vue` 文件中的 `<script>` 块
      {
        test: /\.js$/,
        loader: 'babel-loader'
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin()
  ]
}

上面的配置就是将./src/hello.vue文件编译打包成 ./dist/bundle.js文件,为了能够在打包之后拿到hello.vue组件对象,上面配置了output.library = 'hello'

entry.webpack.html文件中则通过下面方式实例化了一个Vue App

var vm = new Vue({
  el:'#app',
  data: {
    hello: 'hello'
  },
  created() {},
  components:{
    hello: hello.default
  }
});

项目里的entry.fis.html文件为fis编译方式的入口文件,通过运行下面命令来查看效果:

fis3 server start
fis3 release -wcL

本地访问:http://127.0.0.1:8080/entry.fis.html

在fis中已经有大神帮我们实现了.vue文件的编译插件:fis3-parser-vue-component 具体配置如下

// fis-conf.js
fis.match('*.vue', {
  isMod: true,
  rExt: '.js',
  useSameNameRequire: true,
  parser: fis.plugin('vue-component', {
    runtimeOnly: true, // [email protected] 有润timeOnly模式,为ture时,template会在构建时转为render方法, 这里开启后paths中无需指定
    // styleNameJoin
    styleNameJoin: '', // 样式文件命名连接符 `component-xx-a.css`
    extractCSS: false, // 是否将css生成新的文件, 如果为false, 则会内联到js中
    // css scoped
    cssScopedIdPrefix: '_v-', // hash前缀:_v-23j232jj
    cssScopedHashType: 'sum', // hash生成模式,num:使用`hash-sum`, md5: 使用`fis.util.md5`
    cssScopedHashLength: 8 // hash 长度,cssScopedHashType为md5时有效
  }),
  optimizer: [/*fis.plugin('uglify-js'),*/ function(content, file, settings) {
    //console.log(file);
    return content;
  }]
}).match('{*.less, *.vue:less}', {
  parser: fis.plugin('less'),
  postprocessor: fis.plugin('autoprefixer'),
  rExt: '.css'
}).match('{src/**.js, *.vue:js}', {
  parser: fis.plugin('babel-6.x', {
    presets: ['es2015', 'stage-3'],
    plugins: ['add-module-exports']
  }),
  rExt: '.js'
});

上面的两种编译.vue的方法,也只是我们借助工具经过简单配置来实现的,尽管实现了.vue单文件组件的编译,但还是不够友好,或者说我们还是不能方便的使用,他们仍然是要通过编译文件的形式来解析代码,是否可以以一种服务的形式存在直接解析/编译从前端编辑器POST过来的.vue单文件组件代码?我们后面文章将继续介绍~~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK