如何使用 webpack ?
在学习 webpack 之前应该掌握的知识有:
- node
- ES 6
什么是webpack?
webpack 是前端的一个项目构建工具,它是基于 Node.js 开发出来的一个前端工具;
webpack 可以干什么
- 可以处理 js 之间互相依赖的关系
- 可以处理 js 的兼容问题
安装方式
全局安装: (推荐)
npm i webpack -g
项目根目录安装
npm i webpack --save-dev
简单使用
方法一:通过命令打包文件(不推荐)
webpack 要打包的文件路径 打包输出的文件路径
方法二:通过 webpack.config.js
配置文件来打包文件
因为 webpack 是基于 node 开发的打包工具,所以在 webpack.config.js
可以使用 node
let path = require('path');
module.exports = {
entry: path.join(__dirname,'./src/main.js'),//入口文件
output: {
path: path.join(__dirname,'./dist'), //输出文件的路径
filename: 'bundle.js' //指定输出的文件名
}
}
在 webpack.config.js
所在的文件夹中使用命令行工具,输入 webpack
就可以实现打包了
webpack 如何运行?
- 首先,webpack 发现,我们并没有通过命令的形式,给它指定入口和出口
- webpack 就会去项目的根目录中,查找一个叫做
webpack.config.js
的配置文件 - 找到配置文件后,webpack 就会解析执行这个配置文件,当解析执行完配置文件后,就得到了配置文件中,导出的配置对象
- 当 webpack 拿到配置对象后,就拿到了配置对象中,指定的入口和出口,然后进行打包构建
- 如果 webpack 发现既没有 webpack 命令 ,也没有配置文件,他就会报错
使用 webpack-dev-server 自动打包
安装 webpack-dev-server
npm i webpack-dev-server -D
使用 webpack-dev-server
webpack-dev-server 使用方法和 webpack 一样
但是如果在项目中安装 webpack-dev-server,是无法把它当做脚本命令;想在 powershell 终端中直接运行,必须安装到全局 -g
的工具,才能在终端中正常执行.
在本地如何运行 webpack-dev-server 呢?
在 package.json
配置你脚本命令
{
"name": "learn",
"version": "1.0.0",
"description": "",
"main": "webpack.config.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server" // 配置一个名为 dev 的脚本指令
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {},
"devDependencies": {
"jquery": "^3.2.1",
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.3"
}
}
我们直接在本地的命令行下输入 dev
他就会执行 webpack-dev-server
,它其实会开启一个本地的服务器
注意:
webpack-dev-server
这个工具是依赖于 webpack 的,要想使用这个工具,就必须安装 webpackwebpack-dev-server
打包的文件会直接存放在内存中
添加参数
第一种方法:
{
"name": "learn",
"version": "1.0.0",
"description": "",
"main": "webpack.config.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --open --port 3000 --contentBase src --hot" // 添加参数
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {},
"devDependencies": {
"jquery": "^3.2.1",
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.3"
}
}
我们直接在本地的命令行下输入 dev
他就会执行 webpack-dev-server --open --port 3000 --contentBase src --hot
,它其实会开启一个本地的服务器
--open
表示:保存时重新打包,并打开浏览器--port 端口号
表示:开启本地服务器的访问端口号--contentBase 路径
表示:指定根路经--hot
表示:更新打包文件(不是重新创建打包文件),可以实现网页无刷新直接浏览效果,热更新
第二种方法:(比较麻烦)
在 webpack.config.js
文件中进行配置
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: path.join(__dirname,'./src/main.js'),//入口文件
output: {
path: path.join(__dirname,'/dist'),
filename: 'bundle.js' //指定输出的名称
},
devServer: {
open: true,
port: 3000,
contentBase: 'src',
hot: true
},
plugins:[
new webpack.HotModuleReplacementPlugin()
]
}
与第一种方式不一样,使用 webpack 的热更新必须还要加上两步
-
引用 webpack 模块
-
// 在devServer 平级中写入以下东西 plugins:[ new webpack.HotModuleReplacementPlugin() ]
plugins
:是专门放 webpack插件
的地方
使用 html-webpack-plugin 插件
这是一个webpack插件,可以简化HTML文件的创建,并且可以将你指定的打包的文件自动插入到页面中去
安装
npm i --save-dev html-webpack-plugin
使用
- 现在
webpack.config.js
导入要使用的插件 - 配置
const path = require('path');
const webpack = require('webpack');
const htmlWebPackPlugin = require('html-webpack-plugin') // 引用你要使用的插件
module.exports = {
entry: path.join(__dirname,'./src/main.js'),//入口文件
output: {
path: path.join(__dirname,'/dist'),
filename: 'bundle.js' //指定输出的名称
},
devServer: {
open: true,
port: 3000,
contentBase: 'src',
hot: true
},
plugins:[
new webpack.HotModuleReplacementPlugin(),
new htmlWebPackPlugin({
template:path.join(__dirname,'./src/index.html'), // 配置你要在内存中生成的模板文件
filename:'index.html' // 指定内存中的文件名
})
]
}
处理css样式表
webpack
默认只会处理 js 文件,所以在处理其他文件时我们需要安装一些第三方的 loader
加载器
如果我们想要打包处理 css 文件,我们需要安装 style-loader
、css-loader
这两个插件
安装
npm i style-loader css-loader -D
使用
- 在
webpack.config.js
先导入style-loader
、css-loader
- 在
webpack.config.js
配置文件中新增一个配置节点,叫做module
,它是一个对象,在这个module
对象上,有一个rules
属性,它是一个数组,这个数组中存放了所有第三方文件的匹配和处理规则
const path = require('path');
const webpack = require('webpack');
const htmlWebPackPlugin = require('html-webpack-plugin')
console.log(htmlWebPackPlugin);
module.exports = {
entry: path.join(__dirname,'./src/main.js'),//入口文件
output: {
path: path.join(__dirname,'/dist'),
filename: 'bundle.js' //指定输出的名称
},
plugins:[
new htmlWebPackPlugin({
template:path.join(__dirname,'./src/index.html'),
filename:'index.html'
})
],
module: { // 这个节点,用于配置所有第三方模块加载器
rules:[ // 所有第三方模块 匹配规则
{
test: /\.css$/, // 匹配以.css文件结尾的文件
use: ['style.loader','css-loader'] // 指定要处理的.css文件的加载器
}
]
}
}
注意:
webpack 处理第三方文件类型的过程
- 发现这个要处理的文件不是 JS 文件,然后就去配置文件,查找有没有对应的第三方 loader 规则
- 如果能找到对应的规则,就会调用对应的 loader 处理,这种文件类型
- 在调用 loader 的使用,是从后往前调用的
- 当最后一个 loader 调用文件,会把处理的结果,直接交给 webpack 进行打包合并,最终输出到 bundle.js 中去
处理 less 文件
安装
npm i less -D
npm i less-loader -D
使用
const path = require('path');
const webpack = require('webpack');
const htmlWebPackPlugin = require('html-webpack-plugin')
console.log(htmlWebPackPlugin);
module.exports = {
entry: path.join(__dirname,'./src/main.js'),//入口文件
output: {
path: path.join(__dirname,'/dist'),
filename: 'bundle.js' //指定输出的名称
},
plugins:[
new htmlWebPackPlugin({
template:path.join(__dirname,'./src/index.html'),
filename:'index.html'
})
],
module: { // 这个节点,用于配置所有第三方模块加载器
rules:[ // 所有第三方模块 匹配规则
{
test: /\.css$/, // 匹配以.css文件结尾的文件
use: ['style-loader','css-loader'] // 指定要处理的.css文件的加载器
},
{
test: /\.less$/,
use: ['style-loader','css-loader','less-loader']
}
]
}
}
因为 less
编译过来其实也是一种 css 样式,所以我们需要向这样使用 use: ['style-loader','css-loader','less-loader']
处理 scss 文件
安装
npm i sass -D
npm i sass-loader -D
使用
const path = require('path');
const webpack = require('webpack');
const htmlWebPackPlugin = require('html-webpack-plugin')
console.log(htmlWebPackPlugin);
module.exports = {
entry: path.join(__dirname,'./src/main.js'),//入口文件
output: {
path: path.join(__dirname,'/dist'),
filename: 'bundle.js' //指定输出的名称
},
plugins:[
new htmlWebPackPlugin({
template:path.join(__dirname,'./src/index.html'),
filename:'index.html'
})
],
module: { // 这个节点,用于配置所有第三方模块加载器
rules:[ // 所有第三方模块 匹配规则
{
test: /\.css$/, // 匹配以.css文件结尾的文件
use: ['style-loader','css-loader'] // 指定要处理的.css文件的加载器
},
{
test: /\.less$/,
use: ['style-loader','css-loader','less-loader']
},
{
test: /\.scss$/,
use: ['style-loader','css-loader','sass-loader']
}
]
}
}
处理 css 文件中的 url 地址
在默认情况下, webpack 是无法处理 css 文件中的 url 地址,不管是图片还是字体库,只要是 url 地址,就处理不了
因此我们需要 url-loader
、file-loader
,因为 url-loader
依赖 file-loader
安装
npm i url-loader file-loader -D
使用
const path = require('path');
const webpack = require('webpack');
const htmlWebPackPlugin = require('html-webpack-plugin')
console.log(htmlWebPackPlugin);
module.exports = {
entry: path.join(__dirname,'./src/main.js'),//入口文件
output: {
path: path.join(__dirname,'/dist'),
filename: 'bundle.js' //指定输出的名称
},
plugins:[
new htmlWebPackPlugin({
template:path.join(__dirname,'./src/index.html'),
filename:'index.html'
})
],
module: { // 这个节点,用于配置所有第三方模块加载器
rules:[ // 所有第三方模块 匹配规则
{
test: /\.css$/, // 匹配以.css文件结尾的文件
use: ['style-loader','css-loader'] // 指定要处理的.css文件的加载器
},
{
test: /\.less$/,
use: ['style-loader','css-loader','less-loader']
},
{
test: /\.scss$/,
use: ['style-loader','css-loader','sass-loader']
},
{
test: /\.(jpg|png|gif|bmg|jpeg)$/,
use: 'url-loader'
}
]
}
}
url-loader
默认会将图片设置为 base64
进行传递,如果不想设置为 base64
就需要我们将 use: 'url-loader'
设置为 use: 'url-loader?limit=7631&name=[name].[ext]'
- 在
url-loader
设置参数,就像我们浏览器中的url地址一样 - 我们使用
limit
进行设置,limit
后面的值必须设置成小于图片的大小(单位是:字节 byte),这样图片就会以 url 的形式进行传输,否则图片就会被转为 base64格式的字符串进行传值 - 而后面的
name
参数是对客户端浏览器中的文件名进行设置,会将浏览器中图片文件名设置成路径中一样的文件名,因为经过上面的步骤只会将图片的路径设置成hash值
处理字体图片的url路径
在 webpack.config.js
中进行设置
const path = require('path');
const webpack = require('webpack');
const htmlWebPackPlugin = require('html-webpack-plugin')
module.exports = {
entry: path.join(__dirname,'./src/main.js'),//入口文件
output: {
path: path.join(__dirname,'/dist'),
filename: 'bundle.js' //指定输出的名称
},
plugins:[
new htmlWebPackPlugin({
template:path.join(__dirname,'./src/index.html'),
filename:'index.html'
})
],
module: { // 这个节点,用于配置所有第三方模块加载器
rules:[ // 所有第三方模块 匹配规则
{
test: /\.css$/, // 匹配以.css文件结尾的文件
use: ['style-loader','css-loader'] // 指定要处理的.css文件的加载器
},
{
test: /\.less$/,
use: ['style-loader','css-loader','less-loader']
},
{
test: /\.scss$/,
use: ['style-loader','css-loader','sass-loader']
},
{
test: /\.(jpg|png|gif|bmp|jpeg)$/,
use: 'url-loader'
},
{
test: /\.(ttf|eot|svg|woff|woff2)$/,
use:'url-loader'
}
]
}
}
将网页中要使用到字体图片后缀名 ttf
、eot
、svg
、woff
、woff2
进行配置
处理 ES6 的高级语法
在 webpack
中,默认只能处理一部分 ES6 的语法,一些更高级的 ES6 语法 语法或者 ES7 语法,webpack 是处理不了的;这时候,就需要借助于第三方的 loader ,来帮助 webpack 处理这些高级的语法,而第三方的 loader 把高级语法转为低级语法之后,会把结果交给 webpack 去打包到我们要打包的文件中
而我们通过 Babel,可以帮我们将高级的语法转换为低级的语法
在 webpack
中,必须装两套包,才能实现将高级语法转为为低级语法的功能
- 第一套
babel-core
、babel-loader
、babel-plugin-transform-runtime
- 第二套
babel-preset-env
、babel-preset-stage-0
安装
npm i babel-core babel-loader babel-plugin-transform-runtime -D
npm i babel-preset-env babel-preset-stage-0 -D
使用
打开 webpack.config.js
文件,在其中配置处理 ES6 的高级语法
const path = require('path');
const webpack = require('webpack');
const htmlWebPackPlugin = require('html-webpack-plugin')
module.exports = {
entry: path.join(__dirname,'./src/main.js'),//入口文件
output: {
path: path.join(__dirname,'/dist'),
filename: 'bundle.js' //指定输出的名称
},
plugins:[
new htmlWebPackPlugin({
template:path.join(__dirname,'./src/index.html'),
filename:'index.html'
})
],
module: { // 这个节点,用于配置所有第三方模块加载器
rules:[ // 所有第三方模块 匹配规则
{
test: /\.css$/, // 匹配以.css文件结尾的文件
use: ['style-loader','css-loader'] // 指定要处理的.css文件的加载器
},
{
test: /\.less$/,
use: ['style-loader','css-loader','less-loader']
},
{
test: /\.scss$/,
use: ['style-loader','css-loader','sass-loader']
},
{
test: /\.(jpg|png|gif|bmp|jpeg)$/,
use: 'url-loader'
},
{
test: /\.(ttf|eot|svg|woff|woff2)$/,
use:'url-loader'
},
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/ //这是配置 Babel 来转换 ES 的语法
}
]
}
}
注意:
- 在配置 babel 的 loader 规则的时候,必须把
node_modules
目录,通过exclude
选项排除掉,原因有两个:- 如果不排除
node_modules
,则会把node_modules
中所有的第三方 JS 文件都打包编译,这样会非常消耗CPU,同时,打包速度非常慢; - 如果不加上,最终,Babel 把 所用
node_modules
中的 JS 转换完毕了,但是项目依然是无法正常运行的
- 如果不排除
而后,我们必须还要在项目的根目录中,新建一个叫做 .babelrc
的 Babel
配置文件,这个配置文件,属于 JSON 格式,所以,在写 .babelrc
配置的时候,必须符合 JSON 语法规范;不能写注释,字符串必须用双引号,而该文件中写如下内容:
{
"presets": ["env","stage-0"],
"plugins": ["transform-runtime"]
}
在 webpack 中使用网页中的Vue
在 webpack 中,使用 import Vue from vue
导入的 Vue 构造函数功能不完整,只提供了 runtime-only 的方式,并没有提供网页中那样的使用方法;
安装
npm i vue -D
使用
首先在 main.js
中引用 vue,import Vue from 'vue'
而后打开 webpack.config.js
在其中加入一个 resolve
同级的对象,其中加入一个 alias
对象,写入 'vue$': 'vue/dist/vue.min.js'
,它检查到这句话,就会将我们 vue 指向的文件为: vue.min.js
,而不是它默认的指向文件 vue.runtime.common.js
const path = require('path');
const webpack = require('webpack');
const htmlWebPackPlugin = require('html-webpack-plugin')
module.exports = {
entry: path.join(__dirname,'./src/main.js'),//入口文件
output: {
path: path.join(__dirname,'/dist'),
filename: 'bundle.js' //指定输出的名称
},
plugins:[
new htmlWebPackPlugin({
template:path.join(__dirname,'./src/index.html'),
filename:'index.html'
})
],
module: { // 这个节点,用于配置所有第三方模块加载器
rules:[ // 所有第三方模块 匹配规则
{
test: /\.css$/, // 匹配以.css文件结尾的文件
use: ['style-loader','css-loader'] // 指定要处理的.css文件的加载器
},
{
test: /\.less$/,
use: ['style-loader','css-loader','less-loader']
},
{
test: /\.scss$/,
use: ['style-loader','css-loader','sass-loader']
},
{
test: /\.(jpg|png|gif|bmp|jpeg)$/,
use: 'url-loader'
},
{
test: /\.(ttf|eot|svg|woff|woff2)$/,
use:'url-loader'
},
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/
}
]
},
resolve:{
alias:{ // 设置 vue 导入包中的 文件
'vue$': 'vue/dist/vue.min.js'
}
}
}
如何使用 vue.runtime.common.js
在 src 目录中创建一个后缀名为 .vue
的文件 ,其实它就是一个组件
在其中写入:
<template>
</template>
<script>
</script>
<style>
</style>
其中 template
写HTML,script
写 JS,style
写 CSS 。这三部分组成了一个组件,以后我们使用组件的话直接在主文件中引用该文件就可以了。
但是如果运行还是会报错的,我们还必须安装 vue-laoder
注意:
使用 vue.runtime.common.js
要把刚刚在 webpack.config.js
中配置的 resolve
对象给删除掉才行
在 webpack 中配置 vue-loader
安装
npm i vue-loader vue-template-compiler -D
使用
和上面的方法类似,这里就是不详细说明了
const path = require('path');
const webpack = require('webpack');
const htmlWebPackPlugin = require('html-webpack-plugin')
module.exports = {
entry: path.join(__dirname,'./src/main.js'),//入口文件
output: {
path: path.join(__dirname,'/dist'),
filename: 'bundle.js' //指定输出的名称
},
plugins:[
new htmlWebPackPlugin({
template:path.join(__dirname,'./src/index.html'),
filename:'index.html'
})
],
module: { // 这个节点,用于配置所有第三方模块加载器
rules:[ // 所有第三方模块 匹配规则
{
test: /\.css$/, // 匹配以.css文件结尾的文件
use: ['style-loader','css-loader'] // 指定要处理的.css文件的加载器
},
{
test: /\.less$/,
use: ['style-loader','css-loader','less-loader']
},
{
test: /\.scss$/,
use: ['style-loader','css-loader','sass-loader']
},
{
test: /\.(jpg|png|gif|bmp|jpeg)$/,
use: 'url-loader'
},
{
test: /\.(ttf|eot|svg|woff|woff2)$/,
use:'url-loader'
},
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/
},
{
// 处理 .vue 文件的loader
test: /\.vue$/,
use: 'vue-loader'
}
]
}
}
而后,我们运行的还是会报错的,这里必须使用 render 来渲染组件
/**
* 学习在 webpack 中使用 vue
*/
// 注意 : 在 webpack 中,使用 import Vue from `vue` 导入的 Vue 构造函数
// ,功能不完整,只提供了 runtime-only 的方式,并没有提供 网页中那样的使用方法;
import Vue from 'vue';
import login from './login.vue';
let app = new Vue({
el: '#app',
data: {
msg: '123',
},
render:h=> h(login)
})
如果想将组件中的数据导出,必须使用 export default
进行导出
<template>
<h1>我们使用了{{ msg }}</h1>
</template>
<script>
export default {
data: function(){
return {
msg:'nihao'
}
}
}
</script>
<style>
</style>
注意:
export default
是 ES6 中的语法
- 使用
export defalut
向外暴露成员,可以使用import
来接受数据 - 一个模块中
export defalut
只允许向外暴露1次 - 一个模块中
export defalut
和export
可以向外暴露成员
export
也是可以向外暴露成员
- 它导出的成员只能还是用 {} 的形式来接收,这种形式,叫做 【按需导出】
- 它可以向外暴露多个成员,同时这些成员,在使用 import 的时候,不需要,则可以不再 {} 中定义
- 它导出的成员,必须严格按照导出时候的名称,来使用 {} 按需接收,但可以使用 as 来起别名
如何在 webpack 使用 vue-router
安装
npm i vue-router -D
使用
打开 main.js
并且导入 vue-router
,并且使用 Vue.use(VueRouter)
手动挂载 vue-router
import Vue from 'vue';
import app from './app.vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
let vm = new Vue({
el: '#app',
render: c => c(app),
})
而后配置路由:
import Vue from 'vue';
import app from './app.vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
import account from './main/Account.vue';
import goodslist from './main/GoodsList.vue';
let router = new VueRouter({
routes: [
{
path: '/account',
component:account
},
{
path: '/goodslist',
component: goodslist,
}
]
})
let vm = new Vue({
el: '#app',
render: c => c(app),
router
})
这里使用 vue-router
比较麻烦这里配个截图和代码,我不知道怎么解释他们之间的关系,不过要记住每个 .vue
文件就是一个组件
下面是 main.js
的代码
import Vue from 'vue';
import app from './app.vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
import account from './main/Account.vue';
import goodslist from './main/GoodsList.vue';
import login from './subcom/login.vue';
import register from './subcom/register.vue';
let router = new VueRouter({
routes: [
{
path: '/account',
component:account,
children: [
{
path: 'login',
component: login,
},
{
path: 'register',
component: register,
}
]
},
{
path: '/goodslist',
component: goodslist,
}
]
})
let vm = new Vue({
el: '#app',
render: c => c(app),
router
})
下面是组件的代码
account.vue
<template>
<div>
<h1>这是 Account 组件</h1>
<router-link to='/account/login'>登录</router-link>
<router-link to='/account/register'>注册</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
goodslist.vue
<template>
<div>
<h1>这是 GoodsList 组件</h1>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
login.vue
和 register.vue
我就没写内容了,仅仅把它看成子路由就可以了
给子组件加上私有的样式
一般我们在子组件使用样式时,会将所有的样式都改变例如:
<template>
<div>
<h1>这是 Account 组件</h1>
<router-link to='/account/login'>登录</router-link>
<router-link to='/account/register'>注册</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
}
</script>
<style>
div {
color: pink;
}
</style>
当我们点击 account 这个组件是就会触发它自己设置的颜色,从而将整个页面的div中的文字颜色变成粉红色。
而我们仅仅需要给style元素加一个 scoped
属性就会将自己的颜色变成私有的
<template>
<div>
<h1>这是 Account 组件</h1>
<router-link to='/account/login'>登录</router-link>
<router-link to='/account/register'>注册</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
div {
color: pink;
}
</style>
.vue
文件只支持普通的样式,如果想要启用 scss
或 less
,就需要为 style 标签设置 lang
属性
<template>
<div>
<h1>这是 Account 组件</h1>
<router-link to='/account/login'>登录</router-link>
<router-link to='/account/register'>注册</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
}
</script>
<style scoped lang='less'>
div {
color: pink;
a {
color: aqua;
}
}
</style>