古詩詞大全網 - 成語故事 - 詳解vue-loader在項目中是如何配置的

詳解vue-loader在項目中是如何配置的

什麽是vue-loader

這是我入職第三天的故事,在寫這篇文章之前,先來看看咱們今天要講的主角——vue-loader,妳對它了解多少?

這是我今天的回答,確實,vue-loader是webpack的壹個loader,用於處理.vue文件。

.vue 文件是壹個自定義的文件類型,用類 HTML 語法描述壹個 Vue 組件。每個 .vue 文件包含三種類型的頂級語言塊 <template>、<script>和 <style>。

vue-loader 會解析文件,提取每個語言塊,如有必要會通過其它 loader 處理(比如<script>默認用babel-loader處理,<style>默認用style-loader處理),最後將他們組裝成壹個 CommonJS 模塊,module.exports 出壹個 Vue.js 組件對象。

vue-loader 支持使用非默認語言,比如 CSS 預處理器,預編譯的 HTML 模版語言,通過設置語言塊的 lang 屬性。例如,妳可以像下面這樣使用 Sass 語法編寫樣式:

<style lang="sass">

/* write Sass! */

</style>

知道了什麽是vue-loader之後,我們先來創建項目。為了快速地聊聊vue-loader,我在這裏推薦用腳手架工具 @vue/cli 來創建壹個使用 vue-loader 的項目:

npm install -g @vue/cli

vue create hello-world

cd hello-world

npm run serve

這個過程我可以等等妳們,because this might take a while...

當妳在瀏覽器裏輸入localhost:8080之後,瀏覽器會友善地渲染出壹個Welcome to Your Vue.js App的歡迎頁面。

緊接著,我們需要打開妳擅長的編輯器,這裏我選用的是VSCode,順手將項目導入進來,妳會看到最原始的壹個項目工程目錄,裏面只有壹些簡單的項目構成,還沒有vue-loader的配置文件:

首先,我們需要在項目根目錄下面新建壹個webpack.config.js文件,然後開始我們今天的主題。

手動配置css到單獨文件

說到提取css文件,我們應該先去terminal終端去安裝壹下相關的npm包:

npm install extract-text-webpack-plugin --save-dev

先來說個簡答的方法,上代碼:

// webpack.config.js

var ExtractTextPlugin = require("extract-text-webpack-plugin")

module.exports = {

// other options...

module: {

rules: [

{

test: /\.vue$/,

loader: 'vue-loader',

options: {

extractCSS: true

}

}

]

},

plugins: [

new ExtractTextPlugin("style.css")

]

}

上述內容將自動處理 *.vue 文件內的 <style> 提取到style.css文件裏面,並與大多數預處理器壹樣開箱即用。

註意這只是提取 *.vue 文件 - 但在 JavaScript 中導入的 CSS 仍然需要單獨配置。

接下來我們再看看如何手動配置:

// webpack.config.js

var ExtractTextPlugin = require("extract-text-webpack-plugin")

module.exports = {

// other options...

module: {

rules: [

{

test: /\.vue$/,

loader: 'vue-loader',

options: {

loaders: {

css: ExtractTextPlugin.extract({

use: 'css-loader',

fallback: 'vue-style-loader' // 這是vue-loader的依賴

})

}

}

}

]

},

plugins: [

new ExtractTextPlugin("style.css")

]

}

此舉便將所有 Vue 組件中的所有已處理的 CSS 提取到了單個的 CSS 文件。

如何構建生產環境

生產環境打包,目的只有兩個:1.壓縮應用代碼;2.去除Vue.js中的警告。

下面的配置僅供參考:

// webpack.config.js

module.exports = {

// ... other options

plugins: [

new webpack.DefinePlugin({

'process.env': {

NODE_ENV: '"production"'

}

}),

new webpack.optimize.UglifyJsPlugin()

]

}

當然,如果我們不想在開發過程中使用這些配置,有兩種方法可以解決這個問題:

1.使用環境變量動態構建;

例如:const isDev = process.env.NODE_ENV==='development'

或者:const isProd = process.env.NODE_ENV === 'production'

2.使用兩個分開的 webpack 配置文件,壹個用於開發環境,壹個用於生產環境。把可能***用的配置放到第三個文件中。

借鑒大牛的經驗

這裏提供壹個網上標準的寫法,名字叫做vue-hackernews-2.0,這裏是傳送門:/vuejs/vue-hackernews-2.0

其中***用的配置文件webpack.base.config.js的代碼如下:

const path = require('path')

const webpack = require('webpack')

const ExtractTextPlugin = require('extract-text-webpack-plugin')

const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')

const { VueLoaderPlugin } = require('vue-loader')

const isProd = process.env.NODE_ENV === 'production'

module.exports = {

devtool: isProd

? false

: '#cheap-module-source-map',

output: {

path: path.resolve(__dirname, '../dist'),

publicPath: '/dist/',

filename: '[name].[chunkhash].js'

},

resolve: {

alias: {

'public': path.resolve(__dirname, '../public')

}

},

module: {

noParse: /es6-promise\.js$/, // avoid webpack shimming process

rules: [

{

test: /\.vue$/,

loader: 'vue-loader',

options: {

compilerOptions: {

preserveWhitespace: false

}

}

},

{

test: /\.js$/,

loader: 'babel-loader',

exclude: /node_modules/

},

{

test: /\.(png|jpg|gif|svg)$/,

loader: 'url-loader',

options: {

limit: 10000,

name: '[name].[ext]?[hash]'

}

},

{

test: /\.styl(us)?$/,

use: isProd

? ExtractTextPlugin.extract({

use: [

{

loader: 'css-loader',

options: { minimize: true }

},

'stylus-loader'

],

fallback: 'vue-style-loader'

})

: ['vue-style-loader', 'css-loader', 'stylus-loader']

},

]

},

performance: {

maxEntrypointSize: 300000,

hints: isProd ? 'warning' : false

},

plugins: isProd

? [

new VueLoaderPlugin(),

new webpack.optimize.UglifyJsPlugin({

compress: { warnings: false }

}),

new webpack.optimize.ModuleConcatenationPlugin(),

new ExtractTextPlugin({

filename: 'common.[chunkhash].css'

})

]

: [

new VueLoaderPlugin(),

new FriendlyErrorsPlugin()

]

}

然後看看用於開發環境的webpack.client.config.js的配置是如何寫的:

const webpack = require('webpack')

const merge = require('webpack-merge')

const base = require('./webpack.base.config')

const SWPrecachePlugin = require('sw-precache-webpack-plugin')

const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')

const config = merge(base, {

entry: {

app: './src/entry-client.js'

},

resolve: {

alias: {

'create-api': './create-api-client.js'

}

},

plugins: [

// strip dev-only code in Vue source

new webpack.DefinePlugin({

'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),

'process.env.VUE_ENV': '"client"'

}),

// extract vendor chunks for better caching

new webpack.optimize.CommonsChunkPlugin({

name: 'vendor',

minChunks: function (module) {

// a module is extracted into the vendor chunk if...

return (

// it's inside node_modules

/node_modules/.test(module.context) &&

// and not a CSS file (due to extract-text-webpack-plugin limitation)

!/\.css$/.test(module.request)

)

}

}),

// extract webpack runtime & manifest to avoid vendor chunk hash changing

// on every build.

new webpack.optimize.CommonsChunkPlugin({

name: 'manifest'

}),

new VueSSRClientPlugin()

]

})

if (process.env.NODE_ENV === 'production') {

config.plugins.push(

// auto generate service worker

new SWPrecachePlugin({

cacheId: 'vue-hn',

filename: 'service-worker.js',

minify: true,

dontCacheBustUrlsMatching: /./,

staticFileGlobsIgnorePatterns: [/\.map$/, /\.json$/],

runtimeCaching: [

{

urlPattern: '/',

handler: 'networkFirst'

},

{

urlPattern: /\/(top|new|show|ask|jobs)/,

handler: 'networkFirst'

},

{

urlPattern: '/item/:id',

handler: 'networkFirst'

},

{

urlPattern: '/user/:id',

handler: 'networkFirst'

}

]

})

)

}

module.exports = config

最後來看看開發環境中的webpack.server.config.js的配置是怎麽寫的:

const webpack = require('webpack')

const merge = require('webpack-merge')

const base = require('./webpack.base.config')

const nodeExternals = require('webpack-node-externals')

const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')

module.exports = merge(base, {

target: 'node',

devtool: '#source-map',

entry: './src/entry-server.js',

output: {

filename: 'server-bundle.js',

libraryTarget: 'commonjs2'

},

resolve: {

alias: {

'create-api': './create-api-server.js'

}

},

// /liady/webpack-node-externals

externals: nodeExternals({

// do not externalize CSS files in case we need to import it from a dep

whitelist: /\.css$/

}),

plugins: [

new webpack.DefinePlugin({

'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),

'process.env.VUE_ENV': '"server"'

}),

new VueSSRServerPlugin()

]

})

如何進行代碼檢驗

妳可能有疑問,在 .vue 文件中妳怎麽檢驗妳的代碼,因為它不是 JavaScript。我們假設妳使用 ESLint (如果妳沒有使用話,妳應該去使用!)。

首先妳要去安裝eslint-loader:

npm install eslint eslint-loader --save-dev

然後將它應用在pre-loader上:

// webpack.config.js

module.exports = {

// ... other options

module: {

rules: [

{

enforce: 'pre',

test: /\.(js|vue)$/,

loader: 'eslint-loader',

exclude: /node_modules/

}

]

}

}

這樣妳的 .vue 文件會在開發期間每次保存時自動檢驗。