各个社区已经有无数篇帖子介绍如何使用webpack搭建前端项目,但不管是出于学习webpack的目的仍是为了解决工做实际须要都面临着一个现实问题,那就是版本更新。别人的帖子可能刚写好版本就更新了,又要对着帖子找文档。javascript
但这个过程十分重要,由于你想要的一切早已都在文档中给出了说明,在查阅文档的过程当中不但能学会正确的使用工具更加强了阅读文档这种姿式正确的学习能力。css
本文就是记录一次不断遭遇版本问题,一路查阅文档达到学习目的的经历,分享给你们。文章中每一个章节提到的相关文档都会在本章节总结,在文章最后我还会将全部相关文档的连接进行汇总出来方便你们学习。html
第一个要查阅的就是webpack的官方文档,因为webpack近年来的使用普遍,中文文档早已跟上。前端
webpack官方文档: https://webpack.docschina.org/
咱们能够在文档-指南中找到安装相关的内容。vue
webpack安装: https://webpack.docschina.org...
官方已说明不推荐全局安装webpack由于这样会将你项目中的webpack锁定到指定版本。不须要全局安装的可跳过此步骤java
npm i -g webpack
在项目目录下初始化项目会获得package.json文件:node
npm init
webpack4会依赖webpack-cli,若是你没有安装也没必要担忧,npm会直接报错提示你webpack
webpack安装: https://webpack.docschina.org...
webpack-dev-server: https://webpack.docschina.org...
npm i webpack webpack-dev-server webpack-cli --save-dev npm i vue --save
根目录下新建webpack的配置文件webpack.config.js。
配置 入口、出口路径、打包后文件名和devServer的相关配置项es6
使用一个webpack的配置文件: https://webpack.docschina.org...
var path = require('path'); var webpack = require('webpack'); module.exports = { //项目入口文件 entry: './src/main.js', output: { //打包出口路径 path: path.resolve(__dirname, './dist'), //经过devServer访问路径 publicPath: '/dist/', //打包后的文件名 filename: 'main.js' }, mode:'development', devServer: { historyApiFallback: true, overlay: true } };
新建index.html做为项目的主体页面,留出入口文件,入口文件的路径为webpack打包后输出的路径。web
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>webpack-vue</title> <meta name="description" content=""> <meta name="keywords" content=""> </head> <body> <script src="/dist/main.js"></script> </body> </html>
新建在src目录用来存放各类组件和静态文件,在src目录下新建入口文件main.js
为方便开发调试,打包以及后期的代码编写便捷,咱们须要对webpack进行初步配置
package.json 增长 scripts:
"scripts": { "dev": "webpack-dev-server --hot --open", "build": "webpack --mode production --progress --hide-modules" },
这一步的目的是简化在命令行中输入复杂指令的操做,如需执行上述两命令只须要在命令行执行:
npm run dev npm run build
webpack-dev-server --hot --open
目的是开启一个本地服务,--hot
为热加载,可实视查看页面状态,--open
直接从浏览器打开webpack --mode production --progress --hide-modules
是打包整个项目的指令,--mode production
是以生产模式打包,这样会获得体积更小的文件,有兴趣的同窗能够试试不加这个指令,看看差距到底有多大。--progress
打印出编译进度的百分比值,hide-modules
隐藏关于模块的信息
webpack的全部命令行能够在 api-命令行接口(cli) 中找到
webpack命令行接口: https://webpack.docschina.org...
webpack.config.js中增长:
resolve: { //路径别名 alias: { 'vue$': 'vue/dist/vue.esm.js', '@':path.resolve(__dirname, './src'), }, //路径别名自动解析肯定的扩展 tensions: ['.js', '.vue', '.json'] },
resolve
是webpack关于解析的配置项,alias
容许你在项目中使用路径别名代替复杂的路径。extensions
会让webpack自动查找特定后缀的文件,在项目中引入文件时将没必要再书写文件后缀。
至于为什么将vue的路径别名指向vue/dist/vue.esm.js
请看下一章节vue的内容。
webpack解析(resolve): https://webpack.docschina.org...
这一步咱们先暂不考虑使用Vue的单页面组件。
经过查看 node_modules/vue/dist/README.md 咱们能够获得关于webpack配置的说明,引入vue其实是引用 node_modules/vue/dist/vue.esm.js,有理有据安心使用,而且会告诉你若是你在使用webpack 1.0应该引用vue.common.js,这即是上一步配置路径别名的依据。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>webpack-vue</title> <meta name="description" content=""> <meta name="keywords" content=""> </head> <body> <div id="app">{{message}}</div> <script src="/dist/main.js"></script> </body> </html>
import Vue from 'vue' var app = new Vue({ el: "#app", data: { message: 'hello webpack!!' } })
启动server,能够预览到页面显示 'hello webpack!!'。
npm run dev
webpack默认只能解析js文件,所以须要在webpack.config.js中配置相应的解析器。
npm i node-sass css-loader vue-style-loader sass-loader –save-dev
关于webpack解析样式的文档比较散乱,经过粗略查阅,css-loader
用来解析css文件,style-loader
用来解析dom中经过<style></style>
注入的样式,
而vue-style-loader
是vue官方基于style-loader开发的适用于vue的样式解析,sass-loader
用来解析sass/scss文件
webpack - loader: https://webpack.docschina.org...
vue-style-loader: https://www.npmjs.com/package...
module: { rules: [{ test: /\.css$/, use: [ 'vue-style-loader', 'css-loader' ] },{ test: /\.scss$/, use: [ 'vue-style-loader', 'css-loader', 'sass-loader' ] }, { test: /\.sass$/, use: [ 'vue-style-loader', 'css-loader', 'sass-loader?indentedSyntax' ] }] },
以上配置意为:.css
为后缀的文件使用css-loader
, vue-style-loader
解析.scss
和.sass
为后缀的文件使用sass-loader
,css-loader
, vue-style-loader
解析
解析顺序是由下到上的
webpack - module: https://webpack.docschina.org...
webpack - sass-loader: https://webpack.docschina.org...
在src目录下新建目录assets/styles存放统同样式,新建index.scss,写一段scss代码:
$appColor:red; #app{ color:$appColor; }
在main.js中引入样式:
import ‘./assets/styles/index.scss’
再次重启服务能够看到样式已经加载成功了
一样webpack人没法解析图片格式的文件,须要把图片当作模块使用file-loader解析。
file-loader: https://webpack.docschina.org...
npm i file-loader --save-dev
{ test: /\.(png|jpg|gif|svg)$/, loader: 'file-loader', options: { name: '[name].[ext]?[hash]' } }
在src目录下按照代码中路径准备一张图片
Vue.component('myComponent', { template: '<img :src="url" />', data() { return { url: require('./assets/images/logo.png') } } })
在index.html中使用该组件
<div id="app"> {{message}} <my-component></my-component> </div>
重启服务,图片应该被成功加载了。
babel可让咱们在项目中自由的使用es6语法,他会为咱们将es6语法编译成浏览器广泛通用的es5语法。
在此以前咱们必需要对babel有必定的了解:
babel官方文档: https://babel.docschina.org/d...
在babel的使用指南中咱们看到安装babel须要安装的依赖和配置babel的方法。
而且咱们得知一个噩耗,babel从7.0开始与以前版本有写不兼容了。若是你的package.json中babel的版本混乱,很容易形成配置失败。
npm install --save-dev @babel/core @babel/cli @babel/preset-env npm install --save @babel/polyfill
注意:
babel的webpack配置: https://babel.docschina.org/s... 选择webpack
module增长一条rules:
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }
入口文件更改成:
entry: ["@babel/polyfill", './src/main.js'],
注意查看关于env的配置文档,新版本写法有变化。
@babel/preset-env: https://babel.docschina.org/d...
{ "presets": [ [ "@babel/preset-env", { "useBuiltIns": "entry" } ] ] }
在src下新建util.js
export default function getData() { return new Promise((resolve, reject) => { resolve('ok'); }) }
main.js
//引入组件 import getData from './util'; var app = new Vue({ el: "#app", data: { message: 'hello webpack!!' }, methods: { async fetchData() { const data = await getData(); this.message = data; } }, created() { this.fetchData(); } })
import getData from './util';
Can't resolve 'babel-polyfill' in 'E:\vue\webpack-vue'
regeneratorRuntime is not defined
Plugin/Preset files are not allowed to export objects
vue-loader中介绍了如何使用Vue单文件组件:
vue-loader: https://vue-loader.vuejs.org/zh/
npm i vue-loader vue-template-compiler –save-dev
Vue单文件组件: https://vue-loader.vuejs.org/...
// webpack.config.js const VueLoaderPlugin = require('vue-loader/lib/plugin') module.exports = { module: { rules: [ // ... 其它规则 { test: /\.vue$/, loader: 'vue-loader' } ] }, plugins: [ // 请确保引入这个插件! new VueLoaderPlugin() ] }
在src目录下建立文件App.vue
在src目录下新建目录components用来存放单文件组件,新建文件header.vue
App.vue
<template> <div> <home-header user="vict"></home-header> </div> </template> <script> import homeHeader from '@/components/header.vue' export default { name:'app', components:{ homeHeader } } </script> <style lang="scss" scoped> $txtColor:red; .sg{ color:$txtColor } </style>
header.vue(子组件)
<template> <div> header <span>color</span> <img src="@/assets/images/logo.png"> {{this.message}} - {{this.user}} </div> </template> <script> export default { name:'homeHeader', data () { return { message:'hello world' } }, props: { user:String } } </script> <style lang="scss" scoped> span{ color:green } </style>
main.js
import Vue from 'vue' import App from './App.vue' import './assets/styles/index.scss' new Vue({ render:h => h(App) }).$mount('#app')
在.vue中url路径将被解析成webpack模块请求,
这里建议在webpack.config.js中配置路径别名以方便在单文件组件中引用图片等静态资源
在单文件组件中能够这样使用:
<img src="@/assets/images/logo.png">
vue-router: https://router.vuejs.org/zh/
npm i vue-router –save
import Vue from 'vue' import App from './App' //引入router组件 import router from './router/router' import './assets/styles/reset.css' new Vue({ //注入router router, render:h => h(App) }).$mount('#app')
按照路径建立router文件:src/router/router.js
router.js
import Vue from 'vue' import VueRouter from 'vue-router' import Page1 from '@/components/page1' import Page2 from '@/components/page2' Vue.use(VueRouter) export default new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes: [{ path: '/', name:'home', component: Page1 },{ path: '/page2', name:'page2', component: Page2 }] })
常见的渲染失败的缘由:
在App.vue中能够直接使用<router-view>
和<router-link>
标签
vuex: https://vuex.vuejs.org/zh/guide/
npm i vuex –save
import Vue from 'vue' import App from './App' import router from './router/router' import store from './store/store' import './assets/styles/reset.css' new Vue({ router, store, render:h => h(App) }).$mount('#app')
src/store/store.js
可按须要将state、actions、mutations拆分出来
store.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { cur:'OFF', }, actions: { changeCur (ctx,cur) { ctx.commit('changeCueMutations',cur) } }, mutations: { changeCueMutations (state,cur) { cur == 'OFF' ? state.cur = 'ON' :state.cur = 'OFF' } } })
webpack.config.js中若是配置项:mode:'development', build的结果是未通过压缩的很是的大
修改 package.json 中的scripts,将打包时的mode切换成production
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack-dev-server --hot --open", "build": "webpack --mode production --progress --hide-modules" },
webpack官方文档: https://webpack.docschina.org/
webpack安装: https://webpack.docschina.org...
webpack-dev-server: https://webpack.docschina.org...
webpack配置: https://webpack.docschina.org...
webpack命令行接口: https://webpack.docschina.org...
webpack解析(resolve): https://webpack.docschina.org...
webpack - loader: https://webpack.docschina.org...
webpack - module: https://webpack.docschina.org...
Vue官方文档(中文): https://cn.vuejs.org/
Vue-cli: https://cli.vuejs.org/zh/guide/
Vue-router: https://router.vuejs.org/
Vuex: https://vuex.vuejs.org/
Vue-loader(单文件组件): https://vue-loader.vuejs.org/
babel官方文档: https://babel.docschina.org/
babel使用指南: https://babel.docschina.org/d...
babel的配置: https://babel.docschina.org/s...
babel-env: https://babel.docschina.org/d...
npm官方: https://www.npmjs.com/
npm CLI(命令行指令): https://docs.npmjs.com/
vue-style-loader: https://www.npmjs.com/package...
node-sass: https://www.npmjs.com/search?...