文章目录
webpack4发布到现在3个多月的时间,webpack的配置正在向parcelljs靠齐,尽量让用户少配置,不要把时间浪费到配置工具上来。废话不多说,我们一步步来使用webpack4来构建vue2.x 应用。
目标
利用webpack4 打包 vue+ vue-router 应用
1.实现缓存常驻(基本库能够在每次打包没有变化)。
2. 基于路由进行代码分割,实行代码基于路由懒加载
3. 在每次提交代码的时候 利用eslint进行代码的检查,
4. 在编写过程中,能够实现热更新,能够自动打开浏览器。
5.在开发过程中,利用开发服务对api请求使用代理,解决跨域问题
6. 利用jest + vue-test-utils测试框架进行测试
7. 部分UI单元测试采用puppteer测试,如用户的登录注册,各个端的模拟
8. 将每个文件分割成小于200kB的文件(在HTTP2协议中,多个小文件比大文件传输速度快,而且只有一个tcp连接)
本次开发,vue-template 我们使用 pug 模板,css的编写使用stylus预处理语言。现在让我们Let’s rock it.项目地址是https://gitee.com/lmz2423/vue-webpack4/
webpack的基础知识介绍
webpack作为前端开发构建工具的一个利器,因为其配置丰富,生态社区健康成长,有很多可用的第三方插件,而且一切资源都可以打包,深受广大web前端同志喜爱,当然配置丰富,就导致配置负责,优化空间大,这也是webpack的烦恼之一。webpack的官方博客见https://medium.com/webpack
webpack4的到来,目标之一是减少用户的配置,让开发者将更多的时间放在开发,webpack4默认是不需要配置文件的。但是我们还是可以自己编写配置文件,以便精细化处理。
我们先来介绍webpack的四个核心概念
- 入口(entry)
- 输出(output)
- loader
- 插件(plugins)
入口
入口起点指示webpack需要使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。每个依赖项随即被处理,最后输出到称之为 bundles 的文件中。
我们可以看一下下面的例子
module.exports = {
entry: "./src/main.js"
}
出口
output属性告诉webpack在哪里输出它所创建的bundles.以及如何命名这些文件,默认值为.dist
const path = require('path');
module.exports = {
entry: './main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: [main]-[hash].js'
}
};
在上面的示例中,我们通过 output.filename
和 output.path
属性,来告诉 webpack bundle 的名称
loader
loader让webpack能够去处理那些非javascript文件,loader可以将所有类型文件转换webpack能够处理的有效模块。在webpack的配置loader有两个目标
test
属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。- use属性,表示进行转换时,应该使用哪个loader
const path = require('path');
const config = {
output: {
filename: './src/main.js'
},
module: {
rules: [
{ test: /\.jpeg|png|gif/, use: 'file-loader' }
]
}
};
module.exports = config;
插件
loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。如果我们想使用插件,我们只需要引入该插件,然后将它插入到plugins数组中。
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 通过 npm 安装
const webpack = require('webpack'); // 用于访问内置插件
const config = {
module: {
rules: [
{ test: /\.txt$/, use: 'raw-loader' }
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({template: './src/index.html'})
]
};
module.exports = config;
在webpack4中添加了模式(mode) 有两个属性分为development 或production
注意:
1.当我们使用development 时,会将process.env.NODE_ENV的值设置为development 并且启用 NamedChunksPlugin 和 NameModulesPlugin
2.会将 process.env.NODE_ENV
的值设为 production
。启用 FlagDependencyUsagePlugin
, FlagIncludedChunksPlugin
, ModuleConcatenationPlugin
, NoEmitOnErrorsPlugin
, OccurrenceOrderPlugin
, SideEffectsFlagPlugin
和 UglifyJsPlugin。
webpack的基本概念解释清楚了,如果我们想进一步理解可以访问https://webpack.docschina.org/
开始出发
项目地址在https://gitee.com/lmz2423/vue-webpack4
首先我们创建目录 vue-webpack4 .使用mkdir vue-webpack4命令 ,进入 vue-webpack4目录,利用npm init 初始化package.json。
在scripts属性中我们添加如下内容
"scripts": {
"build": "rm -rf dist/ && webpack --config webpack.prd.js ",
"server": "node app.js",
"eslint": "eslint --fix 'src/**/*.vue' 'src/**/*.js'",
"precommit-echo": "echo '正在检查代码格式..' && exit 0",
"test": "jest"
},
build命令是进行项目打包
server 是启动开发程序
eslint 是进行代码格式化检测
precommit-echo 是在commit的时候进行eslint 的提示语
test 是跑测试用例
我们将程序建立在src 目录下。
安装 vue vue-router
我们使用如下命令安装vue vue-router
cnpm install --save-dev vue vue-router
安装webpack工具
在webpack4中我们需要安装webpack-cli 和webpack
安装命令如下
cnpm install -D webpack-cli webpack
建立三个文件 webpack.base.js ,webpack.dev.js, webpack.prd.js, webpack.base.js文件是公用的文件。webpak.dev.js是开发阶段的配置
webpack.prd.js是生产环境的配置
我们现在来想一想,在开发阶段和打包阶段,都需要做的事情是,
- 一编译vue模板代码
- 解析stylus代码
- 解析模板中使用的pug代码
- 解析es6
- 上述的功能都可以提取到webpack.base.js 中
添加webpack.base.js内容
下载babel-core 和babel-loader和babel-preset-env 添加对es6的支持,命令如下
cnpm install --save-dev babel-core babel-loader babel-preset-env
建立.babelrc文件,添加如下内容
{
"presets": [
["env",{
"targets":{
"browsers": ["last 2 versions", "safari >= 7","ie >= 10"]
}
}]
],
}
这样告诉babel编译的js支持所有浏览器的最新两个版本,safari支持到7,ie支持到10.
在webpack.base.js中添加对js解析,添加对pug文件的支持 ,添加对vue模板的支持,
代码如下
const path = require('path')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const base ={
module:{
rules:[
{
test:/\.js$/,
loader:'babel-loader',
include:[
path.resolve(__dirname,"src")
]
},
{
test:/\.vue$/,
loader:"vue-loader",
include:[
path.resolve(__dirname, "src")
]
},
{
test:/\.pug$/,
// 这条规则应用到Vue组件内的`<template lang="pug">`
oneOf:[
{
resourceQuery: /^\?vue/,
use:['pug-plain-loader']
}
]
},
{
test:/\.css$/,
use:[
'style-loader',
'css-loader',
]
},
{
test:/\.styl(us)?$/,
use:[
'vue-style-loader',
'style-loader',
'css-loader',
'stylus-loader'
]
}
]
},
plugins:[
new VueLoaderPlugin({
}),
new HtmlWebpackPlugin({
filename:'index.html',
template:'./src/index.html',
})
]
}
module.exports = base
注意
1,vue-loader npm 从版本15开始需要添加插件,从上述的第二行代码可以看出来。
2. 我们编写entry 和 output入口,主要是在开发阶段,我们需要热更新代码,在生产环境不需要热更新代码。
webpack.dev.js内容
const baseConfig = require('./webpack.base.js')
const path = require('path')
const webpack = require('webpack');
const devConfig = {
devtool: 'inline-source-map',
mode:'development',
entry:[
'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000',
'./src/main.js'
],
output:{
path:path.resolve(__dirname,'dist'),
filename:'[name].[hash].bundle.js',
publicPath:'/'
},
module:{
rules:[
{
test:/\.(png|jpg|jpeg|gif)$/,
loader:'file-loader',
},
]
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
]
}
const merge = require('webpack-merge')
const config = merge(baseConfig,devConfig)
module.exports = config
从上述代码看出相对于webpack4之前,新增了mode 属性 ,mode属性有两个值一个是development ,一个是production,当我们将mode的值设置为development的时候,process.env.NODE_ENV的值设置为 development,此外当development的时候,会加快编译速度,提供有用的错误信息,具体的介绍见官方博客https://medium.com/webpack/webpack-4-mode-and-optimization-5423a6bc597a
这个时候我们配置了开发的webpack文件,这个时候我们使webpackDevMiddleware结合express启动开发服务器。具体配置见下面代码
const express = require('express')
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')
const opn = require('opn')
const app = express()
const config = require('./webpack.dev.js')
const compiler = webpack(config)
const port = 8080
const env = "" //配置哪个环境
const proxy = require('http-proxy-middleware')
const uri = 'http://localhost:' + port
//热更新
const devMiddleware = webpackDevMiddleware(compiler,{
publicPath:config.output.publicPath,
noInfo:true,
})
//此中间件必须在最前面,不然不起作用
app.use(require('connect-history-api-fallback')())
app.use(devMiddleware)
app.use(require("webpack-hot-middleware")(compiler,{
log:false,
path: '/__webpack_hmr',
heartbeat:3000
}))
//代理相关
const proxyTable = {
'/rest/activity': {
target: `http://${env}api-activity.vipkid.com.cn`,
changeOrigin: true,
logLevel: 'debug',
pathRewrite: {
'^/rest/activity': '/'
}
},
'/rest/effect': {
target: `http://${env}.com.cn`,
changeOrigin: true,
logLevel: 'debug',
pathRewrite: {
'^/rest/effect': '/'
}
},
'/rest/learninggw': {
target: `http://${env}.com.cn`,
changeOrigin: true,
logLevel: 'debug',
pathRewrite: {
'^/rest/learninggw': '/'
}
},
'/rest/wechat': {
target: `http://${env}.com.cn`,
changeOrigin: true,
logLevel: 'debug',
pathRewrite: {
'^/rest/wechat': '/'
}
}
}
Object.keys(proxyTable).forEach(context=>{
const options = proxyTable[context]
if(typeof options === 'string'){
options = {
target:options
}
}
app.use(proxy(context, options))
})
const portfinder = require('portfinder')
portfinder.basePort = port
console.log('开始启动 dev server')
devMiddleware.waitUntilValid(()=>{
portfinder.getPort((err, port)=>{
if(err){
console.log(err)
}
console.log("开始侦测" + uri+ '\n')
opn(uri)
app.listen(port)
})
})
webpack-hot-middleware是用来进行热更新的。opn是自动开启系统默认浏览器的。
针对api请求开启了代理。我们在terminal中输入npm run server ,运行效果如下
我们编辑src中的 Index.vue文件 ,看到修改文字和样式会自动更新,如下面视频所示
详细的代码见码云上的代码例子。
代码规范检查
项目开发都需要一份代码规范,如
- 1缩进规范,
- 2.函数没有返回值,不能使用return语句
- 3.不能使用分号
- 条件语句不能出现恒定不变的量
- 不允许出现重复的case的标签
等等代码规范
这个时候我们可以使用eslint来进行规范检查,但是什么时候进行检查呢,如果开发过程中进行检查,那么会影响开发过程,由于大家使用的版本管理工具基本上是git ,git 在 add commit 都有触发的钩子函数,我们可以在commit之前运行eslint
首先 创建eslint规范
我们建立.eslintrc文件,eslintrc的规则可以见eslintrc官网。配置如下
{
"root": true,
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 6,
"ecmaFeatures": {
"experimentalObjectRestSpread": true
},
"sourceType": "module"
},
"globals":{
"page": true,
"browser": true,
"jestPuppeteer": true
},
"env": {
"es6": true,
"jest": true
},
"plugins": [
//插件,此插件用于识别文件中的js代码,没有MIME类型标识没有script标签也可以识别到,因此拿来识别.vue文件中的js代码
"html"
],
"rules": {
//代码规范
}
}
下载pre-commit npm 在package.json中添加pre-commit属性,代码如下
"pre-commit": [
"precommit-echo",
"eslint"
],
precmmit-echo 是scirpts中的命令值,输出正在检查代码规范,我们在Index.vue添加console.log(“xx”) 如下视频所示
到现在为止,我们可以通过eslint + pre-commit 检查代码规范了,pre-commit npm 只能在commit 之前进行代码规范检查,如果想在pre-push阶段,进行单元测试呢。这个时候,我们可以使用husky npm 包来进行命令的配置,具体的配置查看文档。
代码测试
代码测试框架有很多,如Karma, jasmine jest Karma因为测试配置复杂,在本文不提,现在我们使用facebook 开源的测试框架 jest ,配合 vue-test-utils来进行组件测试,具体的配置见各自的官方文档。
发表评论