對vueloader的研究


vue-loaderwebpack的加載器,允許您以稱為單文件組件(SFC)的格式創作Vue組件

<template> <div class="example">{{ msg }}</div> </template> <script> export default { data () { return { msg: 'Hello world!' } } } </script> <style> .example { color: red; } </style>

有許多很酷的功能提供vue-loader

  • 允許對Vue組件的每個部分使用其他webpack加載器,例如Sass for <style>和Pug for <template>;
  • 允許.vue文件中的自定義塊可以應用自定義加載器鏈;
  • 處理在模塊依賴項中引用的靜態資產,<style><template>使用webpack加載器處理它們;
  • 模擬每個組件的范圍CSS;
  • 在開發過程中保持國家的熱再加載。

簡而言之,webpack的組合vue-loader為您提供了一個現代,靈活且極其強大的前端工作流程,用於創作Vue.js應用程序。

Vue的CLI

如果您對手動設置webpack不感興趣,建議使用Vue CLI構建項目Vue CLI創建的項目預先配置了大多數開箱即用的常見開發需求。

如果Vue CLI的內置配置不符合您的需要,請遵循本指南,或者您更願意從頭開始創建自己的webpack配置。

手動配置

Vue Loader的配置與其他加載器略有不同。除了適用vue-loader於任何帶擴展名的文件的規則外,請.vue務必將Vue Loader的插件添加到webpack配置中:

// webpack.config.js const VueLoaderPlugin = require('vue-loader/lib/plugin') module.exports = { module: { rules: [ // ... other rules { test: /\.vue$/, loader: 'vue-loader' } ] }, plugins: [ // make sure to include the plugin! new VueLoaderPlugin() ] } 

這個插件是必需的!它負責克隆您定義的任何其他規則並將它們應用於.vue文件中的相應語言塊例如,如果您有規則匹配/\.js$/,則它將應用於文件中的<script>.vue

一個更完整的webpack配置示例如下所示:

// webpack.config.js const path = require('path') const VueLoaderPlugin = require('vue-loader/lib/plugin') module.exports = { mode: 'development', module: { rules: [ { test: /\.vue$/, loader: 'vue-loader' }, // this will apply to both plain `.js` files // AND `<script>` blocks in `.vue` files { test: /\.js$/, loader: 'babel-loader' }, // this will apply to both plain `.css` files // AND `<style>` blocks in `.vue` files { test: /\.css$/, use: [ 'vue-style-loader', 'css-loader' ] } ] }, plugins: [ // make sure to include the plugin for the magic new VueLoaderPlugin() ] }

資產URL處理

當Vue Loader <template>在SFC中編譯塊時,它還會將遇到的任何資產URL轉換為webpack模塊請求

例如,以下模板代碼段:

<img src="../image.png"> 

將編譯成:

createElement('img', { attrs: { src: require('../image.png') // this is now a module request } }) 

默認情況下,將轉換以下標記/屬性組合,並可使用transformAssetUrls選項進行配置

{ video: ['src', 'poster'], source: 'src', img: 'src', image: 'xlink:href' } 

此外,如果您已配置使用css-loader,則<style>CSS中的資產URL也將以類似的方式處理。

轉換規則

資產URL轉換遵循以下規則:

  • 如果URL是絕對路徑(例如/images/foo.png),則它將按原樣保留。

  • 如果URL以#開頭.,則將其解釋為相對模塊請求,並根據文件系統上的文件夾結構進行解析。

  • 如果URL以...開頭~,則將其解釋為模塊請求。這意味着您甚至可以引用節點模塊內的資產:

    <img src="~some-npm-package/foo.png"> 
  • 如果URL以@,它也被解釋為模塊請求。如果您的webpack配置具有別名@這非常有用,默認情況下,該別名指向/src由其創建的任何項目vue-cli

因為擴展.png不是JavaScript模塊,所以您需要配置webpack以使用file-loaderurl-loader來正確處理它們。使用Vue CLI創建的項目已預先配置。

為什么

資產URL轉換的好處是:

  1. file-loader允許您指定復制和放置資產文件的位置,以及如何使用版本哈希命名它以獲得更好的緩存。此外,這也意味着您只需將圖像放在*.vue文件旁邊,並根據文件夾結構使用相對路徑,而不必擔心部署URL通過適當的配置,webpack將自動將文件路徑重寫為捆綁輸出中的正確URL。

  2. url-loader允許您有條件地將文件內聯為base-64數據URL(如果它們小於給定閾值)。這可以減少普通文件的HTTP請求數量。如果文件大於閾值,則會自動回退到file-loader

使用預處理器

在webpack中,所有預處理器都需要應用相應的加載器。vue-loader允許您使用其他webpack加載器來處理Vue組件的一部分。它將根據lang語言塊屬性和webpack配置中的規則自動推斷要使用的正確加載器

SASS

例如,要<style>使用SASS / SCSS 編譯我們的標記:

npm install -D sass-loader node-sass 

在您的webpack配置中:

module.exports = { module: { rules: [ // ... other rules omitted // this will apply to both plain `.scss` files // AND `<style lang="scss">` blocks in `.vue` files { test: /\.scss$/, use: [ 'vue-style-loader', 'css-loader', 'sass-loader' ] } ] }, // plugin omitted }

現在除了能夠之外import 'style.scss',我們還可以在Vue組件中使用SCSS:

<style lang="scss"> /* write SCSS here */ </style> 

塊中的任何內容都將由webpack處理,就像它在*.scss文件中一樣。

上海社會科學院VS SCSS

請注意,默認情況下sass-loader處理非基於縮進的scss語法。要使用基於縮進的sass語法,您需要將選項傳遞給加載器:

// webpack.config.js -> module.rules { test: /\.sass$/, use: [ 'vue-style-loader', 'css-loader', { loader: 'sass-loader', options: { indentedSyntax: true } } ] }

共享全局變量

sass-loader還支持一個data選項,允許您在所有已處理文件之間共享公共變量,而無需顯式導入它們:

// webpack.config.js -> module.rules { test: /\.scss$/, use: [ 'vue-style-loader', 'css-loader', { loader: 'sass-loader', options: { // you can also read from a file, e.g. `variables.scss` data: `$color: red;` } } ] }

LESS

npm install -D less less-loader 
// webpack.config.js -> module.rules { test: /\.less$/, use: [ 'vue-style-loader', 'css-loader', 'less-loader' ] }

手寫筆

npm install -D stylus stylus-loader 
// webpack.config.js -> module.rules { test: /\.styl(us)?$/, use: [ 'vue-style-loader', 'css-loader', 'stylus-loader' ] }

PostCSS

小費

Vue Loader v15默認不再適用PostCSS變換。您需要使用PostCSS postcss-loader

npm install -D postcss-loader 
// webpack.config.js -> module.rules { test: /\.css$/, use: [ 'vue-style-loader', { loader: 'css-loader', options: { importLoaders: 1 } }, 'postcss-loader' ] } 

PostCSS的配置可以通過postcss.config.jspostcss-loader選項完成有關詳細信息,請參閱postcss-loader docs

postcss-loader 也可以與上述其他預處理器結合使用。

巴貝爾

npm install -D babel-core babel-loader 
// webpack.config.js -> module.rules { test: /\.js?$/, loader: 'babel-loader' } 

Babel的配置可以通過.babelrcbabel-loader選項完成

不包括node_modules

exclude: /node_modules/對於babel-loader適用於.js文件的JS轉換規則(例如通常是常見的由於v15的推斷變化,如果在內部導入Vue SFC node_modules,其<script>部分也將被排除在轉換之外。

為了確保將JS轉換應用於Vue SFC node_modules,您需要使用exclude函數將它們列入白名單:

{ test: /\.js$/, loader: 'babel-loader', exclude: file => ( /node_modules/.test(file) && !/\.vue\.js/.test(file) ) } 

打字稿

npm install -D typescript ts-loader 
// webpack.config.js module.exports = { resolve: { // Add `.ts` as a resolvable extension. extensions: ['.ts', '.js'] }, module: { rules: [ // ... other rules omitted { test: /\.ts$/, loader: 'ts-loader', options: { appendTsSuffixTo: [/\.vue$/] } } ] }, // ... plugin omitted } 

TypeScipt的配置可以通過tsconfig.json另請參閱ts-loader的文檔

帕格

處理模板有點不同,因為大多數webpack模板加載器如pug-loader返回模板函數而不是編譯的HTML字符串。pug-loader我們需要使用一個返回原始HTML字符串的加載器,而不是使用,例如pug-plain-loader

npm install -D pug pug-plain-loader 
// webpack.config.js -> module.rules { test: /\.pug$/, loader: 'pug-plain-loader' } 

然后你可以寫:

<template lang="pug"> div h1 Hello world! </template> 

如果您還打算使用它.pug在JavaScript中將文件作為HTML字符串導入,則需要raw-loader在預處理加載器之后進行鏈接但請注意,添加raw-loader會破壞Vue組件中的使用,因此您需要有兩個規則,其中一個使用a定位Vue文件resourceQuery,另一個(回退)定位JavaScript導入:

// webpack.config.js -> module.rules { test: /\.pug$/, oneOf: [ // this applies to `<template lang="pug">` in Vue components { resourceQuery: /^\?vue/, use: ['pug-plain-loader'] }, // this applies to pug imports inside JavaScript { use: ['raw-loader', 'pug-plain-loader'] } ] }

作用域CSS

<style>標簽具有該scoped屬性時,其CSS將僅應用於當前組件的元素。這類似於Shadow DOM中的樣式封裝。它有一些警告,但不需要任何polyfill。通過使用PostCSS轉換以下內容來實現:

<style scoped> .example { color: red; } </style> <template> <div class="example">hi</div> </template> 

進入以下:

<style> .example[data-v-f3f3eg9] { color: red; } </style> <template> <div class="example" data-v-f3f3eg9>hi</div> </template> 

混合本地和全局樣式

您可以在同一組件中包含范圍和非范圍樣式:

<style> /* global styles */ </style> <style scoped> /* local styles */ </style> 

子組件根元素

使用時scoped,父組件的樣式不會泄漏到子組件中。但是,子組件的根節點將受父級作用域CSS和子級作用域CSS的影響。這是設計的,以便父級可以設置子根元素的樣式以進行布局。

深度選擇器

如果您希望scoped樣式中的選擇器“深入”,即影響子組件,則可以使用>>>組合器:

<style scoped> .a >>> .b { /* ... */ } </style> 

以上將編譯成:

.a[data-v-f3f3eg9] .b { /* ... */ } 

某些預處理器(如Sass)可能無法>>>正確解析在這些情況下,您可以使用/deep/組合器 - 它是別名,>>>並且完全相同。

動態生成的內容

創建的DOM內容v-html不受范圍樣式的影響,但您仍然可以使用深度選擇器設置它們的樣式。

也記住

  • 范圍樣式不會消除類的需要由於瀏覽器呈現各種CSS選擇器的方式,p { color: red }在作用域時(即與屬性選擇器結合時)會慢很多倍。如果您使用類或ID,例如in .example { color: red },那么您幾乎可以消除性能損失。這是一個游樂場,您可以自己測試差異。

  • 在遞歸組件中注意后代選擇器!對於帶有選擇器的CSS規則.a .b,如果匹配的元素.a包含遞歸子組件,則.b該子組件中的所有組件都將與規則匹配。

 

CSS模塊

CSS模塊是用於模塊化和組合CSS的流行系統。vue-loader提供與CSS模塊的一流集成,作為模擬范圍CSS的替代方案。

用法

首先,必須通過傳遞modules: truecss-loader

// webpack.config.js { module: { rules: [ // ... other rules omitted { test: /\.css$/, use: [ 'vue-style-loader', { loader: 'css-loader', options: { // enable CSS Modules modules: true, // customize generated class names localIdentName: '[local]_[hash:base64:8]' } } ] } ] } } 

然后,將module屬性添加到您的<style>

<style module> .red { color: red; } .bold { font-weight: bold; } </style> 

module屬性指示Vue Loader將CSS模塊locals對象作為具有名稱的計算屬性注入組件$style然后,您可以在模板中使用動態類綁定:

<template> <p :class="$style.red"> This should be red </p> </template> 

由於它是一個計算屬性,它也可以使用以下對象/數組語法:class

<template> <div> <p :class="{ [$style.red]: isRed }"> Am I red? </p> <p :class="[$style.red, $style.bold]"> Red and bold </p> </div> </template> 

您還可以從JavaScript訪問它:

<script> export default { created () { console.log(this.$style.red) // -> "red_1VyoJ-uZ" // an identifier generated based on filename and className. } } </script> 

有關模式詳細信息(如全局異常組合),請參閱CSS模塊規范

選擇使用

如果您只想在某些Vue組件中使用CSS模塊,則可以使用oneOf規則並檢查module字符串resourceQuery

// webpack.config.js -> module.rules { test: /\.css$/, oneOf: [ // this matches `<style module>` { resourceQuery: /module/, use: [ 'vue-style-loader', { loader: 'css-loader', options: { modules: true, localIdentName: '[local]_[hash:base64:5]' } } ] }, // this matches plain `<style>` or `<style scoped>` { use: [ 'vue-style-loader', 'css-loader' ] } ] } 

與預處理器一起使用

CSS模塊可以與其他預處理器一起使用:

// webpack.config.js -> module.rules { test: /\.scss$/, use: [ 'vue-style-loader', { loader: 'css-loader', options: { modules: true } }, 'sass-loader' ] } 

自定義進樣名稱

您可以<style>在單個*.vue組件中包含多個標記為避免注入樣式相互覆蓋,可以通過為module屬性賦值來自定義注入的計算屬性的名稱

<style module="a"> /* identifiers injected as a */ </style> <style module="b"> /* identifiers injected as b */ </style>

熱刷新

“Hot Reload”不僅僅是在編輯文件時重新加載頁面。啟用熱重新加載后,在編輯*.vue文件時,將交換該組件的所有實例,而無需重新加載頁面它甚至可以保留您的應用程序和這些交換組件的當前狀態!當您調整組件的模板或樣式時,這可以顯着改善開發體驗。

熱重裝

州保存規則

  • 編輯<template>組件時,已編輯組件的實例將重新呈現,保留所有當前的私有狀態。這是可能的,因為模板被編譯成新的渲染函數,不會產生副作用。

  • 編輯<script>組件一部分時,將銷毀並重新創建已編輯組件的實例。(保留應用程序中其他組件的狀態)這是因為<script>可能包含可能產生副作用的生命周期鈎子,因此需要“重新加載”而不是重新呈現以確保一致的行為。這也意味着您需要注意全局副作用,例如組件生命周期鈎子中的計時器。如果您的組件產生全局副作用,有時您可能需要執行整頁重新加載。

  • <style>熱重載依次運行vue-style-loader,因此不會影響應用程序狀態。

用法

搭建項目時vue-cli,Hot Reload可以開箱即用。

手動設置項目時,在使用項目服務時會自動啟用熱重新加載webpack-dev-server --hot

高級用戶可能想要查看內部使用的vue-hot-reload-apivue-loader

禁用熱重新加載

除以下情況外,始終啟用熱重新加載:

  • webpack targetnode(SSR)
  • webpack縮小了代碼
  • process.env.NODE_ENV === 'production'

您可以使用hotReload: false選項明確禁用熱重新加載:

module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: { hotReload: false // disables Hot Reload } } ] }

功能組件

*.vue文件中定義為單文件組件的功能組件也接收適當的模板編譯,Scoped CSS和熱重載支持。

要表示應編譯為功能組件functional的模板,請將該屬性添加到模板塊。這也允許省略塊中functional選項<script>

模板中的表達式在功能渲染上下文中進行評估這意味着需要像props.xxx在模板中一樣訪問props 

<template functional> <div>{{ props.foo }}</div> </template> 

如果需要訪問全局定義的屬性Vue.prototype,可以在parent以下位置訪問它們

<template functional> <div>{{ parent.$someProperty }}</div> </template>

自定義塊

您可以在*.vue文件中定義自定義語言塊應用於自定義塊的加載器將根據塊的lang屬性,塊的標記名稱以及webpack配置中的規則進行匹配。

如果lang指定屬性,則自定義塊將作為文件lang與其擴展名匹配

您還可以使用resourceQuery匹配自定義塊的規則lang例如,要匹配<foo>自定義塊:

{ module: { rules: [ { resourceQuery: /blockType=foo/, loader: 'loader-to-use' } ] } } 

如果為自定義塊找到匹配規則,則會對其進行處理; 否則將自動忽略自定義塊。

此外,如果自定義塊在所有匹配的加載器處理后將函數導出為最終結果,則將使用*.vue文件的組件作為參數調用該函數

例子

下面是將<docs>自定義塊注入組件的示例,以便在運行時可用。

為了注入自定義塊內容,我們將編寫一個自定義加載器:

module.exports = function (source, map) { this.callback( null, `export default function (Component) { Component.options.__docs = ${ JSON.stringify(source) } }`, map ) } 

現在我們將配置webpack以使用我們的自定義加載器來<docs>定制塊。

// wepback.config.js module.exports = { module: { rules: [ { resourceQuery: /blockType=docs/, loader: require.resolve('./docs-loader.js') } ] } } 

我們現在能夠<docs>在運行時訪問塊的導入組件的內容。

<!-- ComponentB.vue --> <template> <div>Hello</div> </template> <docs> This is the documentation for component B. </docs> 
<!-- ComponentA.vue --> <template> <div> <ComponentB/> <p>{{ docs }}</p> </div> </template> <script> import ComponentB from './ComponentB.vue'; export default { components: { ComponentB }, data () { return { docs: ComponentB.__docs } } } </script>

CSS提取

小費

僅對生產應用CSS提取,以便在開發期間獲得CSS熱重新加載。

的WebPack 4

npm install -D mini-css-extract-plugin 
// webpack.config.js var MiniCssExtractPlugin = require('mini-css-extract-plugin') module.exports = { // other options... module: { rules: [ // ... other rules omitted { test: /\.css$/, use: [ process.env.NODE_ENV !== 'production' ? 'vue-style-loader' : MiniCssExtractPlugin.loader, 'css-loader' ] } ] }, plugins: [ // ... Vue Loader plugin omitted new MiniCssExtractPlugin({ filename: 'style.css' }) ] } 

另請參閱mini-css-extract-plugin文檔

的WebPack 3

npm install -D extract-text-webpack-plugin 
// webpack.config.js var ExtractTextPlugin = require("extract-text-webpack-plugin") module.exports = { // other options... module: { rules: [ // ... other rules omitted { test: /\.css$/, loader: ExtractTextPlugin.extract({ use: 'css-loader', fallback: 'vue-style-loader' }) } ] }, plugins: [ // ... Vue Loader plugin omitted new ExtractTextPlugin("style.css") ] }

Linting

#ESLint

The official eslint-plugin-vue supports linting both the template and script parts of Vue single file components.

Make sure to use the plugin's included config in your ESLint config:

// .eslintrc.js module.exports = { extends: [ "plugin:vue/essential" ] } 

Then from the command line:

eslint --ext js,vue MyComponent.vue

Another option is using eslint-loader so that your *.vue files are automatically linted on save during development:

npm install -D eslint eslint-loader 

Make sure it's applied as a pre-loader:

// webpack.config.js module.exports = { // ... other options module: { rules: [ { enforce: 'pre', test: /\.(js|vue)$/, loader: 'eslint-loader', exclude: /node_modules/ } ] } } 

#stylelint

stylelint supports linting style parts of Vue single file components.

Make sure that your stylelint config is right.

Then from the command line:

stylelint MyComponent.vue

Another option is using stylelint-webpack-plugin:

npm install -D stylelint-webpack-plugin 

Make sure it's applied as a plugin:

// webpack.config.js const StyleLintPlugin = require('stylelint-webpack-plugin'); module.exports = { // ... other options plugins: [ new StyleLintPlugin({ files: ['**/*.{vue,htm,html,css,sss,less,scss,sass}'], }) ] }

測試




















































































 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM