详解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 相关文章推荐
玩转方法:call和apply
May 08 Javascript
angularJS 中input示例分享
Feb 09 Javascript
微信小程序 使用picker封装省市区三级联动实例代码
Oct 28 Javascript
JS查找字符串中出现最多的字符及个数统计
Feb 04 Javascript
使用 Node.js 开发资讯爬虫流程
Jan 07 Javascript
详解VueJS应用中管理用户权限
Feb 02 Javascript
jquery动态添加带有样式的HTML标签元素方法
Feb 24 jQuery
Vue条件循环判断+计算属性+绑定样式v-bind的实例
Sep 18 Javascript
微信小程序登录数据解密及状态维持实例详解
May 06 Javascript
JS实现长图上下滚动效果
Mar 19 Javascript
小程序实现多个选项卡切换
Jun 19 Javascript
JavaScript动画实例之粒子文本的实现方法详解
Jul 28 Javascript
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
雄兵连:第三季确定会出,不过时间未定,鹤熙是第三季的主角!
2020/03/13 国漫
php中长文章分页显示实现代码
2012/09/29 PHP
Laravel 5.5基于内置的Auth模块实现前后台登陆详解
2017/12/21 PHP
PHP多线程模拟实现秒杀抢单
2018/02/07 PHP
PHP使用pdo实现事务处理操作示例
2018/09/05 PHP
phpstorm最新激活码分享亲测phpstorm2020.2.3版可用
2020/11/22 PHP
再次更新!MSClass (Class Of Marquee Scroll通用不间断滚动JS封装类 Ver 1.6)
2007/02/05 Javascript
解决用jquery load加载页面到div时,不执行页面js的问题
2014/02/22 Javascript
node.js中的buffer.Buffer.byteLength方法使用说明
2014/12/10 Javascript
js文本框走动跑马灯效果代码分享
2015/08/25 Javascript
JS表格组件神器bootstrap table详解(基础版)
2015/12/08 Javascript
纯JS焦点图特效实例(可一个页面多用)
2016/12/07 Javascript
vuejs2.0实现分页组件使用$emit进行事件监听数据传递的方法
2017/02/22 Javascript
详解从买域名到使用pm2部署node.js项目全过程
2018/03/07 Javascript
vue里面v-bind和Props 利用props绑定动态数据的方法
2018/08/27 Javascript
解决iview多表头动态更改列元素发生的错误的方法
2018/11/02 Javascript
浅谈Vue服务端渲染框架Nuxt的那些事
2018/12/21 Javascript
[12:36]《DOTA2》国服注册与激活指南全攻略
2013/04/28 DOTA
压缩包密码破解示例分享(类似典破解)
2014/01/17 Python
Django中对数据查询结果进行排序的方法
2015/07/17 Python
python机器学习理论与实战(二)决策树
2018/01/19 Python
python发送告警邮件脚本
2018/09/17 Python
解决Pycharm调用Turtle时 窗口一闪而过的问题
2019/02/16 Python
python多进程下的生产者和消费者模型
2020/05/07 Python
python随机模块random的22种函数(小结)
2020/05/15 Python
Python应用实现双指数函数及拟合代码实例
2020/06/19 Python
python opencv角点检测连线功能的实现代码
2020/11/24 Python
详解Python爬虫爬取博客园问题列表所有的问题
2021/01/18 Python
施华洛世奇加拿大官网:SWAROVSKI加拿大
2018/06/03 全球购物
生物化学研究助理员求职信
2013/10/09 职场文书
2014年干部作风建设总结
2014/10/23 职场文书
史上最牛辞职信
2015/05/13 职场文书
安全生产会议制度
2015/08/06 职场文书
解决Pytorch半精度浮点型网络训练的问题
2021/05/24 Python
WINDOWS 64位 下安装配置mysql8.0.25最详细的教程
2022/03/22 MySQL
mysql 体系结构和存储引擎介绍
2022/05/06 MySQL