详解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 相关文章推荐
最简单的jQuery程序 入门者学习
Jul 09 Javascript
jQuery随便控制任意div隐藏的方法
Jun 28 Javascript
node.js中的path.dirname方法使用说明
Dec 09 Javascript
使用JQuery FancyBox插件实现图片展示特效
Nov 16 Javascript
Jquery 1.9.1源码分析系列(十二)之筛选操作
Dec 02 Javascript
Bootstrap表单布局
Jul 19 Javascript
bootstrapValidator表单验证插件学习
Dec 30 Javascript
vue实现ajax滚动下拉加载,同时具有loading效果(推荐)
Jan 11 Javascript
AngularJS实现自定义指令与控制器数据交互的方法示例
Jun 19 Javascript
教你如何用node连接redis的示例代码
Jul 12 Javascript
区别JavaScript函数声明与变量声明
Sep 12 Javascript
关于Vue Router的10条高级技巧总结
May 06 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连mysql和oracle数据库性能比较
2006/10/09 PHP
用php和MySql来与ODBC数据连接
2006/10/09 PHP
PHP操作数组相关函数
2011/02/03 PHP
PHP导出MySQL数据到Excel文件(fputcsv)
2011/07/03 PHP
php设计模式之命令模式的应用详解
2013/05/21 PHP
解析PHP中intval()等int转换时的意外异常情况
2013/06/21 PHP
PHP如何实现跨域
2016/05/30 PHP
php获取flash尺寸详细数据的方法
2016/11/12 PHP
ThinkPHP5 验证器的具体使用
2018/05/31 PHP
转一个日期输入控件,支持FF
2007/04/27 Javascript
关于全局变量和局部变量的那些事
2013/01/11 Javascript
js使用循环清空某个div中的input标签值
2014/09/29 Javascript
JavaScript编码风格指南(中文版)
2016/08/26 Javascript
深入浅析Nodejs的Http模块
2017/06/20 NodeJs
微信小程序实现点击返回顶层的方法
2017/07/12 Javascript
JavaScript基础心法 深浅拷贝(浅拷贝和深拷贝)
2018/03/05 Javascript
关于JS解构的5种有趣用法
2019/09/05 Javascript
python网络编程学习笔记(一)
2014/06/09 Python
在arcgis使用python脚本进行字段计算时是如何解决中文问题的
2015/10/18 Python
Python实现屏幕截图的代码及函数详解
2016/10/01 Python
python中nan与inf转为特定数字方法示例
2017/05/11 Python
Django实现的自定义访问日志模块示例
2017/06/23 Python
对Python通过pypyodbc访问Access数据库的方法详解
2018/10/27 Python
python字符串循环左移
2019/03/08 Python
关于webview适配H5上传照片或者视频文件的方法
2020/11/04 HTML / CSS
英国第一独立滑雪板商店:The Snowboard Asylum
2020/01/16 全球购物
安全检查管理制度
2014/02/02 职场文书
应聘编辑自荐信范文
2014/03/12 职场文书
多媒体教室标语
2014/06/26 职场文书
打架赔偿协议书范本
2014/10/26 职场文书
捐资助学感谢信
2015/01/21 职场文书
给领导的感谢信范文
2015/01/23 职场文书
毕业生党员个人总结
2015/02/14 职场文书
先进工作者主要事迹材料
2015/11/03 职场文书
《暗黑破坏神2:重制版》本周进行第一轮A测 目前可官网进行申请报名
2021/04/07 其他游戏
pytorch中的numel函数用法说明
2021/05/13 Python