webpack+vue从零开始打造todoList(杰哥课堂)
初步了解Vue,学习的视频是哔哩哔哩的杰哥课堂从零打造前端项目下放链接
视频:https://www.bilibili.com/video/BV157411V7Dh?p=1
文档:http://www.brojie.cn/web/todolist/
安装编译器 vs code,安装环境Node.js
node:https://nodejs.org/zh-cn/
code:https://code.visualstudio.com/Download
如果下载慢可通过百度网盘
链接: https://pan.baidu.com/s/1TeWS-vVUEz78uW809zLSkA 提取码: 4n97 复制这段内容后打开百度网盘手机App,操作更方便哦
①更新
帮助->检测更新(更新最新版重启)
②code汉化
选择扩展ctrl+shift+s 或者 侧边栏打开,输入chinese选择中文简体安装
注意:
①视频中已经讲得很清楚了,其实大部分同学都是在webpack配置上卡住了,因为视频中webpack不是最新版本的,可以使用脚手架(vue-cli)直接进行tudoList开发,也可以选择配置webpack4,所有的安装都带上版本号。不过对于和我一样的初学者,建议还是一步一步配置下来,了解webpack各模板的意义和用法。以后项目中就可以直接使用脚手架,了解原理才能在基础上修改。下面就是项目中我使用的各模块版本
package.json
{
"name": "demo",
"version": "1.0.0",
"description": "使用vue开发todo",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config ./build/webpack.prod.js --progress--display-reason",
"dev": "webpack-dev-server --config ./build/webpack.dev.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.14.6",
"@babel/preset-env": "^7.14.7",
"autoprefixer": "^9.7.4",
"babel-loader": "^8.2.2",
"clean-webpack-plugin": "^4.0.0-alpha.0",
"css-loader": "^3.4.1",
"file-loader": "^5.0.2",
"html-webpack-plugin": "^3.2.0",
"postcss-loader": "^3.0.0",
"style-loader": "^1.1.3",
"stylus": "^0.54.7",
"stylus-loader": "^3.0.2",
"url-loader": "^3.0.0",
"vue-loader": "^15.8.3",
"vue-template-compiler": "^2.6.11",
"webpack": "^4.41.5",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.11.2",
"webpack-merge": "^5.8.0"
},
"dependencies": {
"vue": "^2.6.11"
},
"browserslist": [
"defaults",
"not ie < 11",
"last 2 versions",
"> 1%",
"iOS 7",
"last 3 iOS versions"
]
}
一 项目初始化
新建项目,打开终端ctrl+~
1.init初始化
npm init -y
- init:完成项目初始化, 会生成 package.json 文件
- -y:使用默认选项
2.webpack安装
这里, 我们需要使用 webpack 来完成打包. 因此要安装 webpack 和 webpack-cli
npm install webpack webpack-cli -D
示例:这里我们就可以指定要安装的依赖版本(建议版本都参考上面package.json文件)
npm install webpack@4.41.5 webpack-cli@3.3.10 -D
- install: 安装
- -D:安装开发环境依赖,是--save-dev的简写
安装完成后根目录会添加一个node_modules依赖包文件,在package文件中,就会添加webpack包版本
二 编写项目入口
1. index.html
项目根目录下新建页面index.html(!回车)
2.创建vue根实例
创建src目录,一般src文件夹下放的都是源文件。
创建main.js作为项目入口文件。在main.js中,完成下面操作
- 1.创建vue根实例
- 2.挂载App组件
1)安装vue
npm install vue@2.6.11
@+版本号就会安装对应版本的依赖,如果已经安装过vue,再执行一次就会覆盖原来的版本
2)创建根实例
main.js
// 从vue包中导入Vue对象 import Vue from 'vue' // 创建Vue根实例 new Vue({ el: '#app' })
3)挂载App组件
src下创建App.vue根目录
<template> <div>this is App</div> </template> <script> export default { name: 'App' } </script> <style scoped></style>
挂载到根实例
main.js
//导入实例化vue根实例 import Vue from 'vue'; //从node_modules加载vue对象 //创建vue的根实例 import App from './App.vue' new Vue({ el:"#app", components:{ //组件名:组件对象 App:App //== App }, template:'<App/>' //渲染标签 }) //创建实例,接管html的div#app //挂在app组件
使用App标签渲染
这里的 App 相当于在 components 中定义的组件名
3.引入main.js测试
在index.html 中引入<script>发现报错
因为浏览器不能识别import的这些东西,所以需要webpack打包。
三 webpack基本配置
1.根目录下创建 webpack 配置文件 webpack.config.js
// 使用node的path模块 const path = require('path') module.exports = { // 打包的入口 entry: './src/main.js', // 打包的出口 output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') } }
- entry:指定打包的入口
- output:指定打包的出口, 也就是最终生成的文件
- filename:出口的文件名
- path:路径(根目录新建dist文件夹)
2.编写webpack脚本
packpage.json 中, 创建一个执行脚本
这样就可以使用 "npm run build "执行打包
3.测试
打包命令执行后会报错,那是因为webpack只能执行js文件的打包,后缀vue的文件是不能打包的。所以——
四 vue-loader打包vue文件
loader就是用于打包特定文件的处理程序,后面还有其他loader。
1.安装
vue-loader要和vue-template-compiler一起安装
npm install -D vue-loader@15.8.3vue-template-compiler@2.6.11
2.vue-loader依赖css,把css-loader也安装上
npm install -D css-loader@3.4.1
3.配置webpack.config.js
//引入vue-loader的插件 打包vue const VueLoaderPlugin = require('vue-loader/lib/plugin'); module.exports = { module:{ rules:[ { test:/\.vue$/, loader:'vue-loader' } ] }, plugins:[ new VueLoaderPlugin(), ], resolve:{ //别名配置 alias:{ 'vue':'vue/dist/vue.js' } } }
开头引入,rules为打包规则,其他的loader也要写在rules里,在plugins中引入插件。
避免打包警告,配置打包模式开发者or生产者 mode:'development'
index.html 中引入 bundle.js报错,可以再webpack 中, 添加别名的配置
五 其他loader
一般说,前端出来js文件还有图片文件,css文件等这样的文件都需要安装loader才能进行打包处理
1.打包图片
1)安装file-loader
npm install -D file-loader@5.0.2
添加规则
module: { rules: [ { test: /\.(jpg|jpeg|png|svg)$/, loader: 'file-loader' } ] }
测试
在 src 目录下创建 assets 目录, 存放静态资源文件(如: /images/todolist/styles/fonts 等)在images下存放img
vue文件中引入
import img from './assets/images/xxx.jpg
原理: 当遇到 jpg 结尾的文件时, 使用 file-loader 将文件 copy 到 dist 目录下. 文件名是图片的 hash 值
如果希望保留原有的文件名, 可以使用占位符(placeholder)配置
{ test: /\.(jpg|jpeg|png|svg)$/, loader: 'file-loader', options: { name: '[name].[ext]' } }
[name]
: 占位符, 表示使用原文件名[ext]
: 占位符, 表示使用原文件扩展名
2) url-loader
好处是: 直接将小图片打包以 base64 打包在 js 中, 减少 Http 请求的次数, 提高访问效率
安装 url-loader
由于 url-loader 依赖 file-loader, 因此安装 url-loader 需要先安装 file-loader, 一般来说执行如下命令更适合
npm install -D file-loader url-loader
修改 webpack 配置, 添加一条规则
module: { rules: [ { test: /\.(jpg|jpeg|png|svg)$/, loader: 'url-loader', options: { name: '[name].[ext]', limit: 2048 } } ] }
- test: 正则表达式--如果需要打包的文件以 jpg 或者 jpeg 或者 png 或者 svg 结尾时
- loader: 使用 url-loader
- options: 选项
- limit: 当文件小于 2048byte 时, 以 base64 打包到 js 中, 当文件大于 2048byte 时, 使用 file-loader 打包
- name: 打包的文件名使用"源文件名.扩展名"方式
2.打包css文件
webpack 需要通过 css-loader 和 style-loader 来打包 css 文件
在安装 vue-loader 时, 我们已经安装了 css-loader
所以现在需要安装css-loader
npm install -D style-loader
配置
module: { rules: [{ test: /\.css$/, use: ['style-loader', 'css-loader'] }] },
- test: 正则(以 css 结尾的文件)
- use: 使用两个 loader: style-loader 和 css-loader
注意:这里的书写顺序是有讲究的, 按照从右到左, 从下到上的顺序依次执行
3 打包 stylus 文件
目前, stylus 做为 node 项目普通使用的 css 预处理器被广泛的应用于 vue 项目中. 大家会发现大部分的 vue 项目中都会使用 stylus 来编写 css.
1) 推荐的 vscode 插件与配置
- language-stylus: 提供语法高亮效果和一些支持
- Supremacy: 自动格式化 stylus 的插件, 可以根据个人习惯或公司的要求, 定制 stylus 格式. 比如是否要
;
,:
2) 打包 stylus 文件
安装 stylus-loader
npm install -D stylus stylus-loader
- stylus: 是 stylus 文件预处理程序, 作用是将 stylus 编译成 css 格式
- stylus-loader: 加载 stylus 文件, 调用 stylus 预处理程序形成 css 文件
配置
module: { rules: [{ test: /\.styl(us)?$/, use: ['style-loader', 'css-loader', 'stylus-loader'] }] },
- test: 正则(匹配以 styl 结尾或者 stylus 结尾的文件)
- use: 依次使用 stylus-loader, css-loader, style-loader 处理
测试
css样式就不展示,在 App.vue 中引入 global.styl
import './assets/styles/global.styl'
由于在开发环境, 打包后的文件路径都是相对于 dist 目录, 因此我们还需要暂时把 index.html 移动到 dist 下, 并做如下修改
打包测试完成
3)处理 vue 文件中的 stylus
在前面, 我们已经安装了 stylus 和 stylus-loader, 这里就不用再安装了
直接修改 webpack.config.js配置
module: { rules: [{ test: /\.styl(us)?$/, use: ['vue-style-loader', 'css-loader', 'stylus-loader'] }] },
vue中添加样式
<style lang="stylus" scoped></style>
- 样式用stylus格式
- scoped表示只在当前文件作用
六 插件
1.html-webpack-plugin
作用:打包后产生 dist/index.html,并自动引入打包后js
安装:npm install -D html-webpack-plugin
配置:
var HtmlWebpackPlugin = require('html-webpack-plugin');
plugins:[
new HtmlWebpackPlugin({
template:'./index.html' //指定生成的html是以哪个文件为模板的
}),
]
}
npm install -D clean-webpack-plugin
npm install -D webpack-dev-server
// devServer配置 devServer: { // 指定服务器根目录 contentBase: './dist', // 自动打开浏览器 open: true },
npm run start
启动 devServerconst webpack = require("webpack");//引入webpack module.exports = { devServer: { hot: true,//在服务中开启模块热替换 }, plugins: [new webpack.NamedChunksPlugin(),// 使用了webpack 内置插件 无需再次下载
开发环境(development) 和 生产环境(production) 的构建目标差异很大。在 开发环境 中,我们需要具有强大的、具有实时重新加载(live reloading) 或热模块替换(hot module replacement)能力的 source map 和 localhost server。在 生产环境 中,我们的目标则转向于关注更小的 bundle,更轻量的 source map,以及更优化的资源,以改善加载时间因此, 配置会有所不同, 官方推荐使用两个不同的配置文件webpack.dev.js: 用于开发环境webpack.prod.js: 用于生产环境
// 使用node的path模块 const path = require('path') // 引入vue-loader插件 const VueLoaderPlugin = require('vue-loader/lib/plugin') // 导入html-webpack-plugin const HtmlWebpackPlugin = require('html-webpack-plugin') // 导入clean-webpack-plugin const { CleanWebpackPlugin } = require('clean-webpack-plugin') // 导入webpack const webpack = require('webpack') module.exports = { // 模式 mode: 'development', devtool: 'cheap-module-eval-source-map', // 打包的入口 entry: './src/main.js', // devServer配置 devServer: { // 指定服务器根目录 contentBase: './dist', // 自动打开浏览器 open: true, // 启用热模块替换 hot: true }, // 插件 plugins: [ // 请确保引入这个插件! new VueLoaderPlugin(), new HtmlWebpackPlugin({ template: './index.html' }), new CleanWebpackPlugin(), new webpack.HotModuleReplacementPlugin() ], // 打包的出口 output: { filename: 'app.js', path: path.resolve(__dirname, 'dist') }, // 打包规则 module: { rules: [ { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.(jpg|jpeg|png|svg)$/, loader: 'url-loader', options: { name: '[name].[ext]', limit: 2048 } }, { test: /\.css$/, use: ['style-loader', 'css-loader'] }, { test: /\.styl(us)?$/, use: ['style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'] } ] }, resolve: { alias: { vue: 'vue/dist/vue.js' } } }
// 使用node的path模块 const path = require('path') // 引入vue-loader插件 const VueLoaderPlugin = require('vue-loader/lib/plugin') // 导入html-webpack-plugin const HtmlWebpackPlugin = require('html-webpack-plugin') // 导入clean-webpack-plugin const { CleanWebpackPlugin } = require('clean-webpack-plugin') module.exports = { // 模式 mode: 'production', // 打包的入口 entry: './src/main.js', // 插件 plugins: [ // 请确保引入这个插件! new VueLoaderPlugin(), new HtmlWebpackPlugin({ template: './index.html' }), new CleanWebpackPlugin() ], // 打包的出口 output: { filename: 'app.js', path: path.resolve(__dirname, 'dist') }, // 打包规则 module: { rules: [ { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.(jpg|jpeg|png|svg)$/, loader: 'url-loader', options: { name: '[name].[ext]', limit: 2048 } }, { test: /\.css$/, use: ['style-loader', 'css-loader'] }, { test: /\.styl(us)?$/, use: ['style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'] } ] }, resolve: { alias: { vue: 'vue/dist/vue.js' } } }
"scripts": { "dev": "webpack-dev-server --config ./webpack.dev.js", "build": "webpack --config ./webpack.prod.js" },
npm install -D webpack-merge
webpack.base.js: 公共配置webpack.dev.js: 开发环境配置webpack.prod.js: 生产环境配置
//获取绝对路径 var path=require('path'); //引入vue-loader的插件 打包vue const VueLoaderPlugin = require('vue-loader/lib/plugin'); //const { VueLoaderPlugin } = require('vue-loader') //引入html-webpack-plugin index模板打包生成新的index var HtmlWebpackPlugin = require('html-webpack-plugin'); //引入 clean-webpack-plugin 用于删除上一次的打包内容(打包之前删除js) 需要解构{}语法 const {CleanWebpackPlugin} = require('clean-webpack-plugin'); module.exports = { entry:'./src/main.js', output:{ //path:'./dist/js', //path:path.resolve(__dirname,'./dist/js'), path:path.join(__dirname,'../dist'), filename:'js/app.js' }, module:{ rules:[ { test:/\.vue$/, loader:'vue-loader' },{ test:/\.(png|jpg|gif)$/, // loader:'file-loader', // options:{//配置选项 // name:'[name].[ext]' loader:'url-loader', options:{ name:'[name].[ext]', limit:2048 } },{ test:/\.css$/, use:['style-loader','css-loader'] },{ test:/\.styl(us)?$/, use:['vue-style-loader','css-loader','postcss-loader','stylus-loader'] },{ test:/\.js$/, exclude:/node_modules/, loader:'babel-loader' } ] }, plugins:[ new VueLoaderPlugin(), new HtmlWebpackPlugin({ template:'./index.html' }), new CleanWebpackPlugin(), ], resolve:{ alias:{ 'vue':'vue/dist/vue.js' } } }
const baseConfig = require('./webpack.base.js') const {merge} = require('webpack-merge') //要安装插件webpack-merge实现公共提取 ,视频是const merge = require('webpack-merge'),新版 //要加{} 解构,不是对象 //热模块需要引入webpack插件,导出的是对象 const webpack = require('webpack') //module.exports = { const devConfig = { //合并公共部分,module改造为对象 mode : 'development', //production① devtool:'cheap-module-eval-source-map',//eval(打包速度快)①, 两者都是用于定位到错误行 // devServer配置 devServer: { // 指定服务器根目录 contentBase: './dist', // 自动打开浏览器 open: true, hot:true }, plugins:[ new webpack.HotModuleReplacementPlugin() ] } module.exports= merge(baseConfig,devConfig)
const baseConfig = require('./webpack.base.js') const {merge} = require('webpack-merge') //要安装插件webpack-merge实现公共提取 const prodConfig = { mode : 'production', //production① } module.exports = merge(baseConfig,prodConfig)
"scripts": { "dev": "webpack-dev-server --config ./build/webpack.dev.js", "build": "webpack --config ./build/webpack.prod.js --progress--display-reason" },
在项目中, 有时我们可能会使用 ES6 的语法, 而这些内容在低版本的浏览器上是不支持的. 往往不能正常解析.一般, 我们会使用 babel 将 ES6 编译成 ES5 的语法.babel 的内容是非常丰富的,这里只是演示一些最基本的配置和用法