开篇

前段时间,看到群里一些小伙伴面试的时候被面试官问到这类题目。平时大家开发vue项目的时候,相信大部分人都是使用 vue-cli脚手架生成的项目架构,然后
npm run install 安装依赖,npm run serve启动项目然后就开始写业务代码了。

但是对项目里的webpack封装和配置了解的不清楚,容易导致出问题不知如何解决,或者不会通过webpack去扩展新功能。

该篇文章主要是想告诉小伙伴们,如何一步一步的通过 webpack4来搭建自己的vue开发环境

首先我们要知道 vue-cli生成的项目,帮我们配置好了哪些功能?

  1. ES6代码转换成ES5代码
  2. scss/sass/less/styluscss
  3. .vue文件转换成js文件
  4. 使用 jpgpngfont等资源文件
  5. 自动添加css各浏览器产商的前缀
  6. 代码热更新
  7. 资源预加载
  8. 每次构建代码清除之前生成的代码
  9. 定义环境变量
  10. 区分开发环境打包跟生产环境打包
  11. ....

1. 搭建 webpack 基本环境

该篇文章并不会细讲 webpack 是什么东西,如果还不是很清楚的话,可以先去看看 webpack官网

简单的说,webpack是一个模块打包机,可以分析你的项目依赖的模块以及一些浏览器不能直接运行的语言jsxvue等转换成 jscss文件等,供浏览器使用。

1.1 初始化项目

在命令行中执行 npm init 然后一路回车就行了,主要是生成一些项目基本信息。最后会生成一个 package.json 文件

npm init

1.2 安装webpack

1.3 写点小代码测试一下webpack是否安装成功了

新建一个src文件夹,然后再建一个main.js文件

// src/main.js
console.log('hello webpack')

然后在 package.json 下面加一个脚本命令

然后运行该命令

npm run serve

如果在 dist 目录下生成了一个main.js文件,则表示webpack工作正常

2. 开始配置功能

  • 新建一个 build 文件夹,用来存放 webpack配置相关的文件
  • build文件夹下新建一个webpack.config.js,配置webpack的基本配置
  • 修改 webpack.config.js配置

  • 修改package.json 文件,将之前添加的 serve 修改为
"serve": "webpack ./src/main.js --config ./build/webpack.config.js"

2.1 配置 ES6/7/8ES5代码

  • 安装相关依赖
npm install babel-loader @babel/core @babel/preset-env
  • 修改webpack.config.js配置

  • 在项目根目录添加一个 babel.config.js 文件

  • 然后执行 npm run serve 命令,可以看到 ES6代码被转成了ES5代码了

2.1.1 ES6/7/8 Apies5

babel-loader只会将 ES6/7/8语法转换为ES5语法,但是对新api并不会转换。

我们可以通过 babel-polyfill 对一些不支持新语法的客户端提供新语法的实现

  • 安装
npm install @babel/polyfill
  • 修改webpack.config.js配置

entry 中添加 @babel-polyfill

2.1.2 按需引入polyfill

2.1.2 和 2.1.1 只需要配置一个就行

修改时间 2019-05-05、 来自评论区 兮漫天 的提醒

  • 安装相关依赖
npm install core-js@2 @babel/runtime-corejs2 -S
  • 修改 babel-config.js

配置了按需引入 polyfill 后,用到es6以上的函数,babel会自动导入相关的polyfill,这样能大大减少 打包编译后的体积

2.2 配置 scsscss

在没配置 css 相关的 loader 时,引入scsscss相关文件打包的话,会报错

  • 安装相关依赖
npm install sass-loader dart-sass css-loader style-loader -D

sass-loader, dart-sass主要是将 scss/sass 语法转为css

css-loader主要是解析 css 文件

style-loader 主要是将 css 解析到 html页面 的 style

  • 修改webpack.config.js配置

2.3 配置 postcss 实现自动添加css3前缀

  • 安装相关依赖
npm install postcss-loader autoprefixer -D
  • 修改webpack.config.js配置

  • 在项目根目录下新建一个 postcss.config.js

2.3 使用 html-webpack-plugin来创建html页面

使用 html-webpack-plugin来创建html页面,并自动引入打包生成的js文件

  • 安装依赖
npm install html-webpack-plugin -D
  • 新建一个 public/index.html 页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body><div id="app"></div>
</body>
</html>
  • 修改 webpack-config.js 配置

2.4 配置 devServer 热更新功能

通过代码的热更新功能,我们可以实现不刷新页面的情况下,更新我们的页面

  • 安装依赖
npm install webpack-dev-server -D
  • 修改webpack.config.js配置

通过配置 devServerHotModuleReplacementPlugin 插件来实现热更新

2.5 配置 webpack 打包 图片、媒体、字体等文件

  • 安装依赖
npm install file-loader url-loader -D

file-loader 解析文件url,并将文件复制到输出的目录中

url-loader 功能与 file-loader 类似,如果文件小于限制的大小。则会返回 base64 编码,否则使用 file-loader 将文件复制到输出的目录中

  • 修改 webpack-config.js 配置
    添加 rules 配置,分别对 图片,媒体,字体文件进行配置
// build/webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
module.exports = {// 省略其它配置 ...module: {rules: [// ...{test: /\.(jpe?g|png|gif)$/i,use: [{loader: 'url-loader',options: {limit: 4096,fallback: {loader: 'file-loader',options: {name: 'img/[name].[hash:8].[ext]'}}}}]},{test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,use: [{loader: 'url-loader',options: {limit: 4096,fallback: {loader: 'file-loader',options: {name: 'media/[name].[hash:8].[ext]'}}}}]},{test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,use: [{loader: 'url-loader',options: {limit: 4096,fallback: {loader: 'file-loader',options: {name: 'fonts/[name].[hash:8].[ext]'}}}}]},]},plugins: [// ...]
}

3. 让 webpack 识别 .vue 文件

  • 安装需要的依赖文件
npm install vue-loader vue-template-compiler cache-loader thread-loader -D
npm install vue -S

vue-loader 用于解析.vue文件

vue-template-compiler 用于编译模板

cache-loader 用于缓存loader编译的结果

thread-loader 使用 worker 池来运行loader,每个 worker 都是一个 node.js 进程。

  • 修改 webpack.config.js配置
// build/webpack.config.js
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {// 指定打包模式mode: 'development',entry: {// ...},output: {// ...},devServer: {// ...},resolve: {alias: {vue$: 'vue/dist/vue.runtime.esm.js'},},module: {rules: [{test: /\.vue$/,use: [{loader: 'cache-loader'},{loader: 'thread-loader'},{loader: 'vue-loader',options: {compilerOptions: {preserveWhitespace: false},}}]},{test: /\.jsx?$/,use: [{loader: 'cache-loader'},{loader: 'thread-loader'},{loader: 'babel-loader'}]},// ...]},plugins: [// ...new VueLoaderPlugin()]
}
  • 测试一下
  1. 在 src 新建一个 App.vue
// src/App.vue
<template><div class="App">Hello World</div>
</template><script>
export default {name: 'App',data() {return {};}
};
</script><style lang="scss" scoped>
.App {color: skyblue;
}
</style>
  1. 修改 main.js
import Vue from 'vue'
import App from './App.vue'new Vue({render: h => h(App)
}).$mount('#app')
  1. 运行一下

npm run serve

4. 定义环境变量

通过 webpack提供的DefinePlugin插件,可以很方便的定义环境变量

plugins: [new webpack.DefinePlugin({'process.env': {VUE_APP_BASE_URL: JSON.stringify('http://localhost:3000')}}),
]

5. 区分生产环境和开发环境

新建两个文件

  • webpack.dev.js 开发环境使用
  • webpack.prod.js 生产环境使用
  • webpack.config.js 公用配置

  • 开发环境与生产环境的不同

    5.1 开发环境

  1. 不需要压缩代码
  2. 需要热更新
  3. css不需要提取到css文件
  4. sourceMap
  5. ...

    5.2 生产环境

  6. 压缩代码
  7. 不需要热更新
  8. 提取css,压缩css文件
  9. sourceMap
  10. 构建前清除上一次构建的内容
  11. ...

  • 安装所需依赖
npm i @intervolga/optimize-cssnano-plugin mini-css-extract-plugin clean-webpack-plugin webpack-merge copy-webpack-plugin -D
  1. @intervolga/optimize-cssnano-plugin 用于压缩css代码
  2. mini-css-extract-plugin 用于提取css到文件中
  3. clean-webpack-plugin 用于删除上次构建的文件
  4. webpack-merge 合并 webpack配置
  5. copy-webpack-plugin 用户拷贝静态资源

5.3 开发环境配置

  • build/webpack.dev.js
// build/webpack.dev.js
const merge = require('webpack-merge')
const webpackConfig = require('./webpack.config')
const webpack = require('webpack')
module.exports = merge(webpackConfig, {mode: 'development',devtool: 'cheap-module-eval-source-map',module: {rules: [{test: /\.(scss|sass)$/,use: [{loader: 'style-loader'},{loader: 'css-loader',options: {importLoaders: 2}},{loader: 'sass-loader',options: {implementation: require('dart-sass')}},{loader: 'postcss-loader'}]},]},plugins: [new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('development')}}),]
})
  • webpack.config.js
// build/webpack.config.js
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {entry: {// 配置入口文件main: path.resolve(__dirname, '../src/main.js')},output: {// 配置打包文件输出的目录path: path.resolve(__dirname, '../dist'),// 生成的 js 文件名称filename: 'js/[name].[hash:8].js',// 生成的 chunk 名称chunkFilename: 'js/[name].[hash:8].js',// 资源引用的路径publicPath: '/'},devServer: {hot: true,port: 3000,contentBase: './dist'},resolve: {alias: {vue$: 'vue/dist/vue.runtime.esm.js'},extensions: ['.js','.vue']},module: {rules: [{test: /\.vue$/,use: [{loader: 'cache-loader'},{loader: 'vue-loader',options: {compilerOptions: {preserveWhitespace: false},}}]},{test: /\.jsx?$/,loader: 'babel-loader'},{test: /\.(jpe?g|png|gif)$/,use: [{loader: 'url-loader',options: {limit: 4096,fallback: {loader: 'file-loader',options: {name: 'img/[name].[hash:8].[ext]'}}}}]},{test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,use: [{loader: 'url-loader',options: {limit: 4096,fallback: {loader: 'file-loader',options: {name: 'media/[name].[hash:8].[ext]'}}}}]},{test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,use: [{loader: 'url-loader',options: {limit: 4096,fallback: {loader: 'file-loader',options: {name: 'fonts/[name].[hash:8].[ext]'}}}}]},]},plugins: [new VueLoaderPlugin(),new HtmlWebpackPlugin({template: path.resolve(__dirname, '../public/index.html')}),new webpack.NamedModulesPlugin(),new webpack.HotModuleReplacementPlugin(),]
}

5.4 生产环境配置

const path = require('path')
const merge = require('webpack-merge')
const webpack = require('webpack')
const webpackConfig = require('./webpack.config')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssnanoPlugin = require('@intervolga/optimize-cssnano-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = merge(webpackConfig, {mode: 'production',devtool: '#source-map',optimization: {splitChunks: {cacheGroups: {vendors: {name: 'chunk-vendors',test: /[\\\/]node_modules[\\\/]/,priority: -10,chunks: 'initial'},common: {name: 'chunk-common',minChunks: 2,priority: -20,chunks: 'initial',reuseExistingChunk: true}}}},module: {rules: [{test: /\.(scss|sass)$/,use: [{loader: MiniCssExtractPlugin.loader},{loader: 'css-loader',options: {importLoaders: 2}},{loader: 'sass-loader',options: {implementation: require('dart-sass')}},{loader: 'postcss-loader'}]},]},plugins: [new webpack.DefinePlugin({'process.env': {NODE_ENV: 'production'}}),new MiniCssExtractPlugin({filename: 'css/[name].[contenthash:8].css',chunkFilename: 'css/[name].[contenthash:8].css'}),new OptimizeCssnanoPlugin({sourceMap: true,cssnanoOptions: {preset: ['default',{mergeLonghand: false,cssDeclarationSorter: false}]}}),new CopyWebpackPlugin([{from: path.resolve(__dirname, '../public'),to: path.resolve(__dirname, '../dist')}]),new CleanWebpackPlugin()]
})

5.5 修改package.json

"scripts": {"serve": "webpack-dev-server --config ./build/webpack.dev.js","build": "webpack --config ./build/webpack.prod.js"
},

6 打包分析

有的时候,我们需要看一下webpack打包完成后,到底打包了什么东西,

这时候就需要用到这个模块分析工具了 webpack-bundle-analyzer

  • 安装依赖
npm install --save-dev webpack-bundle-analyzer
  • 修改webpack-prod.js配置,在 plugins属性中新增一个插件

在开发环境中,我们是没必要进行模块打包分析的,所以我们将插件配置在了生产环境的配置项中

  • 运行打包命令
npm run build

执行成功后会自动打开这个页面

7. 集成 VueRouter,Vuex

  1. 首先是安装相关依赖
npm install vue-router vuex --save

7.1 集成 Vue-Router

  • 新增视图组件
    src 目录下新增两个视图组件 src/views/Home.vuesrc/views/About.vue
// src/views/Home.vue
<template><div class="Home"><h2>Home</h2></div>
</template><script>
export default {name: 'Home',data() {return {};}
};
</script><style lang="scss" scoped>
</style>

About.vue 内容跟 Home.vue 差不多,将里面的 Home 换成 About 就OK了

  • 新增路由配置文件

src 目录下新增一个 router/index.js 文件

// src/router/index.js
import Vue from 'vue'
import VueRouter from "vue-router";
import Home from '../views/Home';
import About from '../views/About';
Vue.use(VueRouter)
export default new VueRouter({mode: 'hash',routes: [{path: '/Home',component: Home},{path: '/About',component: About},{path: '*',redirect: '/Home'}]
})
  • 修改 main.js 文件
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'new Vue({router,render: h => h(App)
}).$mount('#app')
  • 修改 App.vue 组件
// App.vue
// 在 template 中添加
// src/App.vue
<template><div class="App">Hello World</div><div>// router-link 组件 用来导航到哪个路由<router-link to="/Home">go Home</router-link><router-link to="/About">go About</router-link></div><div>// 用于展示匹配到的路由视图组件<router-view></router-view></div>
</template><script>
export default {name: 'App',data() {return {};}
};
</script><style lang="scss" scoped>
.App {color: skyblue;
}
</style>

运行 npm run serve 命令,如没配置错误,是可以看到点击不同的路由,会切换到不同的路由视图

7.2 配置路由懒加载

在没配置路由懒加载的情况下,我们的路由组件在打包的时候,都会打包到同一个js文件去,当我们的视图组件越来越多的时候,就会导致这个 js 文件越来越大。然后就会导致请求这个文件的时间变长,最终影响用户体验

  1. 安装依赖
npm install @babel/plugin-syntax-dynamic-import --save-dev
  1. 修改babel.config.js
module.exports = {presets: [["@babel/preset-env",{useBuiltIns: "usage"}]],plugins: [// 添加这个'@babel/plugin-syntax-dynamic-import']
}
  1. 修改 router/index.js 路由配置文件
import Vue from 'vue'
import VueRouter from "vue-router";
Vue.use(VueRouter)
export default new VueRouter({mode: 'hash',routes: [{path: '/Home',component: () => import(/* webpackChunkName: "Home" */ '../views/Home.vue')// component: Home},{path: '/About',component: () => import(/* webpackChunkName: "About" */ '../views/About.vue')// component: About},{path: '*',redirect: '/Home'}]
})
  1. 运行命令 npm run build
    查看是否生成了 Home...js 文件 和 About...js 文件

7.3 集成 Vuex

  1. src 目录下新建一个 store/index.js 文件
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {counter: 0
}
const actions = {add: ({commit}) => {return commit('add')}
}
const mutations = {add: (state) => {state.counter++}
}
const getters = {getCounter (state) {return state.counter}
}
export default new Vuex.Store({state,actions,mutations,getters
})
  1. 修改 main.js 文件 导入 vuex
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'  // ++
new Vue({router,store,    // ++render: h => h(App)
}).$mount('#app')
  1. 修改 App.vue ,查看 vuex 配置效果
// App.vue
<template><div class="App"><div><router-link to="/Home">go Home</router-link><router-link to="/About">go About</router-link></div><div><p>{{getCounter}}</p><button @click="add">add</button></div><div><router-view></router-view></div></div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
export default {name: 'App',data() {return {};},computed: {...mapGetters(['getCounter'])},methods: {...mapActions(['add'])}
};
</script>
<style lang="scss" scoped>
.App {text-align: center;color: skyblue;font-size: 28px;
}
</style>
  1. 运行命令 npm run serve

当点击按钮的时候,可以看到我们的getCounter一直在增加

8 总结

到目前为止,我们已经成功的自己搭建了一个 vue 开发环境,不过还是有一些功能欠缺的,有兴趣的小伙伴可以交流交流。在搭建过程中,还是会踩很多坑的。

如果还不熟悉 webpack 的话,建议自己搭建一次。可以让自己能深入的理解 vue-cli 替我们做了什么

推荐阅读

  1. 使用 webpack 的各种插件提升你的开发效率

  2. vue-cli3 项目从搭建优化到docker部署

  3. Event Loop 原来是这么回事

  4. 通过vue-cli3构建一个SSR应用程序

欢迎关注

欢迎关注公众号“码上开发”,每天分享最新技术资讯

转载于:https://www.cnblogs.com/lentoo/p/10897939.html

面试官:自己搭建过vue开发环境吗?相关推荐

  1. vscode搭建vue开发环境(vue入门)

    本文基于vue2.0版本,文末说明怎么升级为vue3.0版本 一.安装VScode 从官网下载,安装就行.以下操作在win+r -> cmd 命令行界面执行.在vscode中就是在创建好的项目空 ...

  2. vue开发环境搭建Mac版

    一.前言 因工作缘故,需要做一个移动端app,面对2016下半年至今webapp最流行的三个技术React,angular,vue,三选一,如何先,经过前期的技术选型,最后决定使用vue.具体查看本人 ...

  3. laravel+vue开发环境搭建

    From: https://www.jianshu.com/p/1c2cc11ba46f 描述 最近通过laravel在公司做了一些项目,但本身前端出身的我,总是感觉lphp开发过程中,前端写好页面, ...

  4. 初探webpack之从零搭建Vue开发环境

    初探webpack之搭建Vue开发环境 平时我们可以用vue-cli很方便地搭建Vue的开发环境,vue-cli确实是个好东西,让我们不需要关心webpack等一些繁杂的配置,然后直接开始写业务代码, ...

  5. 168.Vue.js智能扫码点餐系统(二)【搭建Vue开发环境】2019.03.18

    0.知识点 搭建开发环境 1.搭建Vue开发环境 2.安装vue-cli脚手架 安装命令 // 第一种: npm install --global vue-cli// 第二种 cnpm install ...

  6. 离线/内网环境下搭建vue开发环境

    系列文章目录 第一讲 离线/内网环境下搭建vue开发环境 第二讲 内网环境运行maven项目 目录 外网环境搭建 一.安装nodeJS 二.安装vue依赖包 内网环境正式开始 准备工作: 一.安装no ...

  7. Vue 开发环境搭建(Mac 版)

    Vue 开发环境搭建(Mac 版) 参考: https://www.jianshu.com/p/cc722eba1f46 https://www.runoob.com/w3cnote/vue2-sta ...

  8. Macbook搭建vue开发环境

    一.Vue2.0推荐开发环境 注:上面的图片转自Vue2.0 新手入门 - 从环境搭建到发布 本人使用的各个工具的版本为: Homebrew 3.4.6 node.js v17.9.0 npm 8.5 ...

  9. 「从源码中学习」面试官都不知道的Vue题目答案

    前言 当回答面试官问及的Vue问题,我们除了照本宣科的回答外,其实还可以根据少量的源码来秀一把,来体现出你对Vue的深度了解. 本文会陆续更新,此次涉及以下问题: "new Vue()做了什 ...

最新文章

  1. python难学?对初学者不友好?进来看看,每30s就能学会一个小技巧,你get到了嘛?
  2. 利用ionic3进行上一行和左一行不动,中间移动的功能
  3. 阿里云天池 金融风控训练营Task1 广东工业站
  4. sqlserver 日期函数
  5. shiro自定义过滤器
  6. JavaScript 是一种什么样的语言
  7. Exception in thread http-apr-8080-exec-
  8. Ajax 滚动异步加载数据
  9. urllib携带登录信息
  10. 【笔记】【一文解决】linux - grep、sed、awk 『三剑客』
  11. Classic Shell 后继者之 Classic Start
  12. 形式语言与自动机 Part.4 正则语言,2DFA,MealyMoore机
  13. C++ yaml解析实战暨yaml-cpp库使用(1)认识yaml格式
  14. 数据结构——图的创建以及遍历
  15. Android直播软件搭建左滑右滑清屏控件
  16. [项目]——文件搜索工具Java-Everything
  17. 计算机名弹出输入网络密码错误,win10系统登录网络打印机出现用户名和密码错误的设置办法...
  18. 深度学习系列之随机梯度下降(SGD)优化算法及可视化
  19. 南通五年制计算机大专学校,南通比较好的五年制的大专有哪些
  20. C语言 全局变量和局部变量的特点

热门文章

  1. 如何反编译.apk(注:CSDN上提供的资源过时了,都用不了)
  2. ubuntu16.04 安装apache2报错 解决方案
  3. 怎么对MySQL数据库操作大数据?这里有思路
  4. [Android]对MVC和MVP的总结
  5. Android 性能优化案例
  6. F5解决方案– 教育行业解决方案1(分析篇)
  7. ASP.net控件开发系列之(一、二)
  8. 还是不知道怎么用FreeTextBox 3.0,郁闷致死
  9. LeetCode 994. 腐烂的橘子
  10. select下拉框如何触发函数并传递参数