深入浅出的webpack构建工具--webpack4+vue搭建环境 (十三)
深入浅出的webpack构建工具--webpack4+vue搭建环境 (十三)
从上面一系列的webpack配置的学习,我们现在来使用webpack来搭建vue的开发环境。首先我们来设想下我们的项目的目录结构如下:
### 目录结构如下:
demo1 # 工程名
| |--- dist # 打包后生成的目录文件
| |--- node_modules # 所有的依赖包
| |--- app
| | |---index
| | | |-- views # 存放所有vue页面文件
| | | |-- components # 存放vue公用的组件
| | | |-- app.js # vue入口配置文件
| |--- views
| | |-- index.html # html文件
| |--- webpack.config.js # webpack配置文件
| |--- .gitignore
| |--- README.md
| |--- package.json
| |--- .babelrc # babel转码文件
因此需要依赖package.json文件配置如下:
{
  "name": "vue项目架构",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack-dev-server --progress --colors --devtool cheap-module-eval-source-map --hot --inline",
    "build": "webpack --progress --colors --devtool cheap-module-source-map",
    "build:dll": "webpack --config webpack.dll.config.js"
  },
  "author": "tugenhua0707@qq.com",
  "sideEffects": false,
  "license": "ISC",
  "devDependencies": {
    "add-asset-html-webpack-plugin": "^2.1.3",
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.5",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-env": "^1.7.0",
    "babel-preset-stage-2": "^6.24.1",
    "clean-webpack-plugin": "^0.1.19",
    "css-loader": "^1.0.0",
    "cssnano": "^4.0.5",
    "extract-text-webpack-plugin": "^4.0.0-beta.0",
    "file-loader": "^1.1.11",
    "happypack": "^5.0.0",
    "html-webpack-plugin": "^3.2.0",
    "lodash-es": "^4.17.11",
    "mini-css-extract-plugin": "^0.4.2",
    "path": "^0.12.7",
    "postcss-cssnext": "^3.1.0",
    "postcss-loader": "^3.0.0",
    "postcss-pxtorem": "^4.0.1",
    "postcss-sprites": "^4.2.1",
    "style-loader": "^0.21.0",
    "stylus": "^0.54.5",
    "stylus-loader": "^3.0.2",
    "uglifyjs-webpack-plugin": "^1.2.7",
    "url-loader": "^1.0.1",
    "vue-loader": "^15.4.2",
    "vue-style-loader": "^4.1.2",
    "vue-template-compiler": "^2.5.17",
    "webpack": "^4.16.1",
    "webpack-cli": "^3.0.8",
    "webpack-deep-scope-plugin": "^1.6.0",
    "webpack-dev-server": "^3.1.4",
    "webpack-parallel-uglify-plugin": "^1.1.0"
  },
  "dependencies": {
  }
}
接着项目 views/index.html 代码初始化如下:
<!DOCTYPE html>
<html>
<head>
<title>webpack4+vue项目架构</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
</head>
<body>
<div id="app">
</div> </body>
</html>
.babelrc 转码文件代码如下:
{
  "plugins": [
     [
      "transform-runtime",
      {
        "polyfill": false
      }
     ]
   ],
   "presets": [
     [
       "env",
       {
         "modules": false   // 关闭Babel的模块转换功能,保留ES6模块化语法
       }
     ],
     "stage-2"
  ]
}
我们现在在 app/index/views 下新建一个test.vue 代码如下:
<style lang="stylus"> </style> <template>
<div class='app-container'>
<div>
<p v-if="datas.length > 0" v-for="(item, index) in datas">{{item}}</p>
</div>
</div>
</template> <script type="text/javascript">
export default {
data() {
return {
datas: [1, 2, 3, 4]
}
}
}
</script>
如上代码文件是vue文件,因此我们需要安装vue-loader等插件,安装命令如下:
npm i -D vue-loader css-loader vue-template-compiler vue-style-loader
vue框架运行需要的库,命令如下:
npm i --save vue
上面依赖的作用如下:
vue-loader: 解析和转换.vue文件,提取出其中的逻辑代码script,样式代码style及html模板template,再分别将他们交给对应的Loader去处理。
css-loader: 加载由vue-loader提取出的css代码。
vue-template-compiler: 将vue-loader 提取出的HTML模板编译成对应的可执行javascript代码。
然后我们编写下 app/index/app.js 的入口文件简单的代码如下:
import Vue from 'vue';
import Test from './views/test';
new Vue({
  el: '#app',
  render: h => h(Test)
});
接着 webpack.config.js 代码配置如下:
const path = require('path');
// 引入 mini-css-extract-plugin 插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 清除dist目录下的文件
const ClearWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
// 引入打包html文件
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 引入HappyPack插件
const HappyPack = require('happypack');
// 引入 ParallelUglifyPlugin 插件
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
// 引入 webpack-deep-scope-plugin 优化
const WebpackDeepScopeAnalysisPlugin = require('webpack-deep-scope-plugin').default;
module.exports = {
  // 入口文件
  entry: {
    main: './app/index/app.js'
  },
  output: {
    filename: process.env.NODE_ENV === 'production' ? '[name].[contenthash].js' : 'bundle.js',
    // 将输出的文件都放在dist目录下
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        // 使用正则去匹配
        test: /\.styl$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {}
          },
          {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              plugins: [
                require('postcss-cssnext')(),
                require('cssnano')(),
                require('postcss-pxtorem')({
                  rootValue: 16,
                  unitPrecision: 5,
                  propWhiteList: []
                }),
                require('postcss-sprites')()
              ]
            }
          },
          {
            loader: 'stylus-loader',
            options: {}
          }
        ]
      },
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'happypack/loader?id=css-pack'
        ]
      },
      {
        test: /\.(png|jpg)$/,
        use: ['happypack/loader?id=image']
      },
      {
        test: /\.js$/,
        // 将对.js文件的处理转交给id为babel的HappyPack的实列
        use: ['happypack/loader?id=babel'],
        // loader: 'babel-loader',
        exclude: path.resolve(__dirname, 'node_modules') // 排除文件
      },
      {
        test: /\.vue$/,
        use: ['happypack/loader?id=vue-loader'],
        exclude: path.resolve(__dirname, 'node_modules') // 排除文件
      }
    ]
  },
  resolve: {
    extensions: ['*', '.js', '.json', '.vue']
  },
  devtool: 'cheap-module-eval-source-map',
  devServer: {
    port: 8081,
    host: '0.0.0.0',
    headers: {
      'X-foo': '112233'
    },
    inline: true,
    overlay: true,
    stats: 'errors-only'
  },
  mode: 'development', // 开发环境下
  // mode: 'production',
  plugins: [
    new HtmlWebpackPlugin({
      template: './views/index.html' // 模版文件
    }),
    new ClearWebpackPlugin(['dist']),
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash:8].css'
    }),
    /****   使用HappyPack实例化    *****/
    new HappyPack({
      // 用唯一的标识符id来代表当前的HappyPack 处理一类特定的文件
      id: 'babel',
      // 如何处理.js文件,用法和Loader配置是一样的
      loaders: ['babel-loader']
    }),
    new HappyPack({
      // 用唯一的标识符id来代表当前的HappyPack 处理一类特定的文件
      id: 'vue-loader',
      // 如何处理.js文件,用法和Loader配置是一样的
      loaders: ['vue-loader']
    }),
    new HappyPack({
      id: 'image',
      loaders: [{
        loader: require.resolve('url-loader'),
        options: {
          limit: 10000,
          name: '[name].[ext]'
        }
      }]
    }),
    // 处理styl文件
    new HappyPack({
      id: 'css-pack',
      loaders: ['css-loader']
    }),
    // 使用 ParallelUglifyPlugin 并行压缩输出JS代码
    new ParallelUglifyPlugin({
      // 传递给 UglifyJS的参数如下:
      uglifyJS: {
        output: {
          /*
           是否输出可读性较强的代码,即会保留空格和制表符,默认为输出,为了达到更好的压缩效果,
           可以设置为false
          */
          beautify: false,
          /*
           是否保留代码中的注释,默认为保留,为了达到更好的压缩效果,可以设置为false
          */
          comments: false
        },
        compress: {
          /*
           是否在UglifyJS删除没有用到的代码时输出警告信息,默认为输出,可以设置为false关闭这些作用
           不大的警告
          */
          warnings: false,
          /*
           是否删除代码中所有的console语句,默认为不删除,开启后,会删除所有的console语句
          */
          drop_console: true,
          /*
           是否内嵌虽然已经定义了,但是只用到一次的变量,比如将 var x = 1; y = x, 转换成 y = 5, 默认为不
           转换,为了达到更好的压缩效果,可以设置为false
          */
          collapse_vars: true,
          /*
           是否提取出现了多次但是没有定义成变量去引用的静态值,比如将 x = 'xxx'; y = 'xxx'  转换成
           var a = 'xxxx'; x = a; y = a; 默认为不转换,为了达到更好的压缩效果,可以设置为false
          */
          reduce_vars: true
        }
      }
    }),
    new WebpackDeepScopeAnalysisPlugin()
  ]
};
然后我们运行 npm run dev 后,打包报错了:如下:

vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.
通过百度搜索后,网上都说需要引入 VueLoaderPlugin 的webpack组件,webpack如下引入方式:
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
  plugins: [
    new VueLoaderPlugin()
  ]
}
引入后,再运行还会报错,如下信息:
Error: [VueLoaderPlugin Error] No matching use for vue-loader is found.
Make sure the rule matching .vue files include vue-loader in its use.
我这边是使用的是"vue-loader": "^15.4.2", 我刚开始以为是 vue-loader 版本的问题了,然后当我修改版本到14版本后,还是会报错,然后在github上搜索这个答案,发现老外也提了这样的问题,说是不是版本的问题,最后尤雨溪回答,这和vue-loader版本没有关系,最后我搜索到 vue-loader 15.1, 它不支持happypack这个插件优化,可以看github(https://github.com/vuejs/vue-loader/issues/1339)上的提示,有了这个提示,我直接把webpack中和vue相关的 happypack的优化去掉,然后打包既然就可以了。
因此webpack中的vue配置就变成如下:
module.exports = {
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: ['vue-loader']
      }
    ]
  }
}
一切准备就绪后,我们现在运行 npm run dev 后,会运行如下所示:

然后我们就可以在浏览器下 运行 http://0.0.0.0:8081/ 就可以看到vue页面了,当我们继续修改 test.vue的时候, 保存后更新。
理想是美好的,现实是残酷的,但是当我一切认为可以的时候,然后我们把对应的<style lang="stylus">样式加上,如下代码:
<style lang="stylus" >
.app-container
width 200px
</style>
<template>
<div class='app-container'>
<div>
<p v-if="datas.length > 0" v-for="(item, index) in datas">{{item}}</p>
</div>
</div>
</template> <script type="text/javascript">
export default {
data() {
return {
datas: [5, 2, 3, 4]
}
}
}
</script>
继续打包,就报这样的错误了;如下:
Module parse failed: Unexpected token (2:0)
You may need an appropriate loader to handle this file type.
|
> .app-container
| width 200px
最后github搜索,发现 webpack4 不兼容vue-loader 15.x.x版本,github点击查看(https://github.com/airyland/vux/issues/3060)或者可以看这个(https://segmentfault.com/a/1190000014586699)
然后我把vue-loader 改成 "vue-loader": "^14.2.2",然后继续打包, 就没有问题了。
如下运行结果:

二:webpack4上如何提取css文件到单独的文件
webpack4以上貌似不能使用mini-css-extract-plugin提取css文件,比如我在代码里面这样写:
new MiniCssExtractPlugin({
  filename: process.env.NODE_ENV === 'production' ? 'css/[name].[contenthash:8].css' : '[name].css',
  chunkFilename: process.env.NODE_ENV === 'production' ? 'css/[id].[contenthash:8].css' : '[id].css'
}),
但是貌似提取不了,看到说webpack4还是可以用extract-text-webpack-plugin 只不过安装的时候插件名加个@next,于是就改用
extract-text-webpack-plugin来提取这个插件就可以打包在一个css文件内.
因此我们现在安装命令如下:
npm i extract-text-webpack-plugin@next -D
然后在webpack.config.js 这样配置代码即可:
// 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")
]
}
运行结构如下所示;可以看到css文件被提取出来了。

具体可以看官方文档(https://vue-loader-v14.vuejs.org/zh-cn/configurations/extract-css.html)
下面是github上的源码:
基于webpack4+vue 单页面(https://github.com/tugenhua0707/webpack-all-demo/tree/master/webpack%2Bvue)
深入浅出的webpack构建工具--webpack4+vue搭建环境 (十三)的更多相关文章
- 深入浅出的webpack构建工具--webpack4+vue+router项目架构(十四)
		阅读目录 一:vue-router是什么? 二:vue-router的实现原理 三:vue-router使用及代码配置 四:理解vue设置路由导航的两种方法. 五:理解动态路由和命名视图 六:理解嵌套 ... 
- 深入浅出的webpack构建工具---webpack基本配置(一)
		深入浅出的webpack构建工具---webpack基本配置(一) 阅读目录 一:webpack入门构建: 1. 安装webpack到全局 2. 安装webpack到本项目. 3. 如何使用webpa ... 
- 深入浅出的webpack构建工具---AutoDllPlugin插件(八)
		深入浅出的webpack构建工具---AutoDllPlugin插件(八) DllPlugin插件能够快速打包,能把第三方依赖的文件能提前进行预编译打包到一个文件里面去.提高了构建速度.因为很多第三方 ... 
- 深入浅出的webpack构建工具---DevServer配置项(二)
		深入浅出的webpack构建工具---DevServer配置项(二) 阅读目录 DevServer配置项 1. contentBase 2. port 3. host 4. headers 5. hi ... 
- 深入浅出的webpack4构建工具--webpack4+vue+route+vuex项目构建(十七)
		阅读目录 一:vue传值方式有哪些? 二:理解使用Vuex 三:webpack4+vue+route+vuex 项目架构 回到顶部 一:vue传值方式有哪些? 在vue项目开发过程中,经常会使用组件来 ... 
- 深入浅出的webpack构建工具---PostCss(五)
		一:PostCss是什么? PostCss是一个样式处理工具,它通过自定义的插件和工具生态体系来重新定义css.它鼓励开发者使用规范的css原生语法编写代码,然后配置编译器转换需要兼容的浏览器版本, ... 
- 深入浅出的webpack构建工具---HappyPack优化构建(九)
		阅读目录 一:什么是HappyPack? 作用是什么? 二:如何在配置中使用HappyPack? 回到顶部 一:什么是HappyPack? 作用是什么? Webpack是允许在NodeJS中的,它是单 ... 
- 深入浅出的webpack4构建工具--webpack4+vue+vuex+mock模拟后台数据(十九)
		mock的官网文档 mock官网 关于mockjs的优点,官网这样描述它:1)可以前后端分离.2)增加单元测试的真实性(通过随机数据,模拟各种场景).3)开发无侵入(不需要修改既有代码,就可以拦截 A ... 
- 深入浅出的webpack构建工具---DllPlugin DllReferencePlugin提高构建速度(七)
		阅读目录 一:什么是DllPlugin 和 DllReferencePlugin?作用是什么? 二:在项目中如何使用 DllPlugin 和 DllReferencePlugin? 三:DllPlug ... 
随机推荐
- Java学习笔记之——常用转义符号
			\ 单独用会报错 \\ 打印右斜杠 \n 换行 \t Tab键 \" 双引号 \' 单引号 
- CDN使用心得:加速双刃剑
			文章图片存储在GitHub,网速不佳的朋友,请看<CDN 使用心得:加速双刃剑> 或者 来我的技术小站 godbmw.com 本文以腾讯云平台的 CDN 服务为例,记录下在个人网站开发和公 ... 
- Linux常用基本命令:三剑客命令之-awk内置变量与自定义变量
			AWK中,变量分为两种:内置变量与自定义变量. 常见的内置变量有: FS:输入字段分隔符, 默认为空白字符 OFS:输出字段分隔符, 默认为空白字符 RS:输入记录分隔符(输入换行符), 指定输入时的 ... 
- javascript基础知识学习
			javascript中几种基础函数的介绍 1.typeof 注意: ① typeof 是操作符,不是函数: ② typeof 操作符 接收一个参数,用来判断参数数据类型,存在六种返回值类型,非别是:u ... 
- JavaScript中的window对象的属性和方法;JavaScript中如何选取文档元素
			一.window对象的属性和方法 ①setTimeout()方法用来实现一个函数在指定毫秒之后运行,该方法返回一个值,这个值可以传递给clearTimeout()用于取消这个函数的执行. ②setIn ... 
- nginx报错zero size shared memory zone   one
			为了限速,在虚拟主机中加上了一个参数:limit_conn one 1:结果导致重启nginx报错: zero size shared memory zone "one"解决办法是 ... 
- 深入研究HTML5实现图片压缩上传
			上篇文章中提到移动端上传图片,我们知道现在流量还是挺贵的,手机的像素是越来越高,拍个照动不动就是好几M,伤不起.虽然客户端可以轻轻松松实现图片压缩再上传,但是我们的应用还可能在浏览器里面打开,怎么办呢 ... 
- 关于input的焦点事件
			关于input的焦点事件 $(".scanf_integral").focus(function(){//获取焦点//获取焦点后触发的事件 }) $(".scanf_in ... 
- 用Web Services来整合.NET和J2EE
			互用性(Interoperability)问题说起来容易但通常实现起来却比较困难.尽管Web service曾承诺要提供最佳的解决方案来衔接基于.NET和J2EE的应用程序,但其过程却并不简单.我们发 ... 
- 在Apex中使用sObject
			sObject对象的定义 Salesforce中的标准对象或自定义对象在Apex中使用时被称作"sObject".sObject对象的一个实例相当于Salesforce中的一条记录 ... 
