详解vue-loader在项目中是如何配置的


Posted in Javascript onJune 04, 2018

什么是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...

详解vue-loader在项目中是如何配置的

当你在浏览器里输入localhost:8080之后,浏览器会友善地渲染出一个Welcome to Your Vue.js App的欢迎页面。

紧接着,我们需要打开你擅长的编辑器,这里我选用的是VSCode,顺手将项目导入进来,你会看到最原始的一个项目工程目录,里面只有一些简单的项目构成,还没有vue-loader的配置文件:

详解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,这里是传送门:https://github.com/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'
  }
 },
 // https://webpack.js.org/configuration/externals/#externals
 // https://github.com/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 文件会在开发期间每次保存时自动检验。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
取消选中单选框radio的三种方式示例介绍
Dec 23 Javascript
javascript实现链接单选效果的方法
May 13 Javascript
详解jQuery中的元素的属性和相关操作
Aug 14 Javascript
node网页分段渲染详解
Sep 05 Javascript
jQuery 防止相同的事件快速重复触发方法
Feb 08 jQuery
Vue 页面切换效果之 BubbleTransition(推荐)
Apr 08 Javascript
JS实现移动端触屏拖拽功能
Jul 31 Javascript
jQuery解析json格式数据示例
Sep 01 jQuery
JS实现的Object数组去重功能示例【数组成员为Object对象】
Feb 01 Javascript
微信小程序 setData 对 data数据影响问题
Apr 18 Javascript
手把手带你入门微信小程序新框架Kbone的使用
Feb 25 Javascript
详解vue中使用transition和animation的实例代码
Dec 12 Vue.js
vue.js打包之后可能会遇到的坑!
Jun 03 #Javascript
详解vue项目中如何引入全局sass/less变量、function、mixin
Jun 02 #Javascript
vue之将echart封装为组件
Jun 02 #Javascript
React学习笔记之高阶组件应用
Jun 02 #Javascript
浅谈node中的cluster集群
Jun 02 #Javascript
详解AngularJS 过滤器的使用
Jun 02 #Javascript
简化vuex的状态管理方案的方法
Jun 02 #Javascript
You might like
PHP无敌近乎加密方式!
2010/07/17 PHP
php切割页面div内容的实现代码分享
2012/07/31 PHP
phpQuery占用内存过多的处理方法
2013/11/13 PHP
php 判断服务器操作系统的类型
2014/02/17 PHP
通过curl模拟post和get方式提交的表单类
2014/04/23 PHP
PHP调用.NET的WebService 简单实例
2015/03/27 PHP
php+MySql实现登录系统与输出浏览者信息功能
2016/07/01 PHP
php的扩展写法总结
2019/05/14 PHP
PHP 对象继承原理与简单用法示例
2020/04/21 PHP
jquery中attr和prop的区别分析
2015/03/16 Javascript
Jquery判断radio、selelct、checkbox是否选中及获取选中值方法总结
2015/04/15 Javascript
AngularJS基础学习笔记之控制器
2015/05/10 Javascript
vuejs父子组件之间数据交互详解
2017/08/09 Javascript
Vue 自定义动态组件实例详解
2018/03/28 Javascript
Node.js console控制台简单用法分析
2019/01/04 Javascript
使用webpack搭建vue项目实现脚手架功能
2019/03/15 Javascript
[01:08:10]2014 DOTA2国际邀请赛中国区预选赛 SPD-GAMING VS LGD-CDEC
2014/05/22 DOTA
Python 调用DLL操作抄表机
2009/01/12 Python
Linux环境下MySQL-python安装过程分享
2015/02/02 Python
详解Python网络爬虫功能的基本写法
2016/01/28 Python
PyQt5 QSerialPort子线程操作的实现
2018/04/21 Python
python实现对任意大小图片均匀切割的示例
2018/12/05 Python
Python 调用有道翻译接口实现翻译
2020/03/02 Python
Python定义一个函数的方法
2020/06/15 Python
获取python运行输出的数据并解析存为dataFrame实例
2020/07/07 Python
纯CSS3实现的阴影效果
2014/12/24 HTML / CSS
丝芙兰香港官网:Sephora香港
2018/03/13 全球购物
英国女性时尚鞋类的潮流制造者:Koi Footwear
2018/10/19 全球购物
Maisons du Monde德国:法国家具和装饰的市场领导者
2019/07/26 全球购物
英国旅行箱包和行李箱购物网站:Travel Luggage & Cabin Bags
2019/08/26 全球购物
卡拉威高尔夫官方网站:Callaway Golf
2020/09/16 全球购物
北京银河万佳Java面试题
2012/03/21 面试题
毕业生个人求职信范文分享
2014/01/05 职场文书
优秀食品类广告词
2014/03/19 职场文书
局机关干部群众路线个人对照检查材料思想汇报
2014/10/05 职场文书
关于保护环境的建议书
2019/06/24 职场文书