萌新誤入vue-loader洞穴 -- sourcemap

今天的主線任務是,稍微瞭解下vue-loader的sourcemapjavascript

這裏簡單記錄下打怪經歷css

故事背景

大祭司布魯梅爾,跟玩家說在傑羅瓦鎮的西北方有一個迷宮,裏面有個被關閉了300年的魔物,咱們須要把這個魔物幹掉,正好以此來測試下玩家是否具有"開啓者"的資格,也就是戰鬥系轉職資格。html

因而做爲勇士的我來到了傑村,獲取鑰匙
圖片描述vue

圖片描述

任務以前,先說一下,有很多法蘭城的勇士,並不喜歡它,有人說它違反了webpack自定義loader的精神,不支持inlineTemplate(具體這個inlineTemplate是什麼鬼?)...java

引自https://webpack.github.io/doc...webpack

do only a single task

Loaders can be chained. Create loaders for every step, instead of a loader that does everything at once.git

This also means they should not convert to JavaScript if not necessary.github

Example: Render HTML from a template file by applying the query parameters
I could write a loader that compiles the template from source, execute it and return a module that exports a string containing the HTML code. This is bad.web

做爲萌新的我,並不知道vue-loader發生了什麼了,只能說一臉蒙逼chrome

可是我心裏其實以爲vue-loader做爲一個vue配套的工具,仍是挺不錯的

懷揣這樣的心情,就來到了門口
圖片描述

二話不說,正式開幹

怎麼說呢,仍是先了解下vue-loader的做用,它能夠transform以vue結尾的文件,從而達到一些目的,好比單文件component, hot reload, scope css...

項目結構

clipboard.png

這裏要了解的sourcemap,都在parser.js文件中

source code分析

引入的外部模塊

var compiler = require('vue-template-compiler')
var cache = require('lru-cache')(100)
var hash = require('hash-sum')
var SourceMapGenerator = require('source-map').SourceMapGenerator
  • lru-cache,lru緩存,vue1.0內部也用的

  • hash-sum,其簡介爲Blazing fast unique hash generator,用於生成hash

  • soruce-map,一個咱們生成sourcemap主要的依賴庫,這裏用的其屬性爲SourceMapGenerator的類

  • vue-template-compiler,模塊發現是vue內部的代碼,爲src/entries/web-compiler.js文件,這個模塊是由vue的build/build.js,使用rollup生成的packager,哦? 少年好像又學到了什麼。具體vue-template-compiler搞了什麼,暫時無論,先標個紅

generateSourceMap函數

function generateSourceMap (filename, source, generated) {
  var map = new SourceMapGenerator()
  map.setSourceContent(filename, source)
  generated.split(splitRE).forEach((line, index) => {
    if (!emptyRE.test(line)) {
      map.addMapping({
        source: filename,
        original: {
          line: index + 1,
          column: 0
        },
        generated: {
          line: index + 1,
          column: 0
        }
      })
    }
  })
  return map.toJSON()
}

判斷空行的目的是,這樣的話,那些空白行就不會生成map,減小map體積

chrome調試的時候,那些空白行也是灰的,不必打斷點嘛

而後,那個換行正則也是頗有意思,外服的玩家討論了一番,https://github.com/webpack/we...
結論就是g這樣的flag,js容易出問題的,好比你能夠在控制檯裏感覺下:

var r = /\n/g;
console.log(r.test("\n")); // => true
console.log(r.test("\n")); // => false

解決是,要嗎將正則的屬性lastIndex = 0,要嗎將g去掉

導出函數

module.exports = function (content, filename, needMap) {
  var cacheKey = hash(filename + content)
  // source-map cache busting for hot-reloadded modules
  var filenameWithHash = filename + '?' + cacheKey
  var output = cache.get(cacheKey)
  if (output) return output
  output = compiler.parseComponent(content, { pad: true })
  if (needMap) {
    if (output.script && !output.script.src) {
      output.script.map = generateSourceMap(
        filenameWithHash,
        content,
        output.script.content
      )
    }
    if (output.styles) {
      output.styles.forEach(style => {
        if (!style.src) {
          style.map = generateSourceMap(
            filenameWithHash,
            content,
            style.content
          )
        }
      })
    }
  }
  cache.set(cacheKey, output)
  return output
}

任務途中,突遇掉線,果真很魔力

掉線回城,東門醫院補血,繼續任務

這裏舉個例子,而後理解下
index.html

<div id="app"></div>

src/index.js

const Vue = require('vue')
const Hello = require('./Hello.vue')

new Vue({
  el: '#app',
  components: {
    Hello: Hello
  },
  render: function(h) {
    return h(
      'Hello'
    )
  }
})

src/Hello.vue

<template>
  <div class="hello">
    <span>hello</span>
  </div>
</template>

<script>
module.exports = {
  created() {
    console.log('hello .vue file')
  }
}
</script>

<style scoped>
.hello {
  font-size: 12px;
}
</style>

而後以此例來分析下,

3個參數

  • content: Hello.vue中的文件內容

  • filename: Hello.vue

  • needMap: webpack配置中若是dev-tools使用了'source-map'... 則爲true

調用compiler.parseComponent(content, { pad: true }),會解析成下面的格式,
稍微注意style是一個數組的形式,便可以有多個style標籤

而後這些標籤其實能夠有src屬性,表示引入外部對應的文件,好比這裏判斷了!output.script.src

{ 
  template: { 
    type: 'template',
    content: '\n<div class="hello">\n  <span>hello</span>\n</div>\n',
    start: 10,
    end: 65 
  },
  script: {
    type: 'script',
    content: '//\n//\n//\n//\n//\n//\n\nmodule.exports = {\n  created() {\n   console.log(\'hello .vue file\')\n  }\n}\n',
    start: 86,
    end: 161 
  },
  styles: [
    { 
      type: 'style',
      content: '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.hello {\n  font-size: 12px;\n}\n',
      start: 186,
      scoped: true,
      end: 217 
    }
  ],
  customBlocks: [] 
}

戰鬥結束

圖片描述
圖片描述

ok,沒怎麼費血瓶,順利獲取重要道具:大地翼龍的鱗片1個,下一層繼續出發

相關文章
相關標籤/搜索