项目初始化
-
创建项目文件夹
-
npm init
初始化 -
安装局部webpack、webpack-cli
-
在package.json中编写script脚本
"scripts": { "build": "webpack" }, // 这样就可以使用npm run build 打包了 // 参考官方 https://www.webpackjs.com/guides/production/#npm-scripts
-
创建vue项目的目录及文件
配置
在webpack.config.js文件中编写webpack配置,基础结构如下
// webpack.config.js
const path = require('path')
module.exports = {
entry: ...,
output: ...,
module:[...],
plugins:[...]
}
模式Mode
提供 mode
配置选项,告知 webpack 使用相应模式的内置优化,默认值时production
模式(Mode) | webpack 中文文档 (docschina.org)
module.exports = {
mode: 'development',
};
image-20220616140824661.png
入口entry
entry
用于配置入口,也是webpack管理的依赖关系的起点。
配置 | webpack 中文网 (webpackjs.com)
entry:'./src/main.js'
出口output
output
用于配置输出,也就是webpack打包后的文件存放在哪里。
配置 | webpack 中文网 (webpackjs.com)
output: {
path: path.resolve(__dirname, 'dist'), // 用path.resolve拼接得到一个绝对路径
filename: 'js/bundle.js',
clean: true, // 清空输出目录,webpack5开始可以直接配置清空,不再需要安装CleanWebpackPlugin
},
配置loader
loader用于对模块源代码进行转换,loader遇到不知道如何加载的文件/模块时,就需要对应的loader来进行加载。loader存放在module.rules数组中,Rule的几个常用属性:test
用于资源匹配;use
是一个对象,用来设置loader及loader的options;loader
use的简写
Loaders | webpack 中文文档 (docschina.org)
module:{
rules:[
... // loader规则Rule对象
]
}
css相关的loader
css-loader
css-loader是用来处理.css
文件的
先安装 npm install --save-dev css-loader
在rules数组中配置规则 ,这样就可以打包css文件了{test: /\.css$/,loader: 'css-loader',}
style-loader
用了css-loader
虽然可以打包css文件了,但是现在的css样式还没效果,需要使用style-loader
将css插入到页面中
安装npm install style-loader -D
在rules数组中配置规则,loader的加载顺序是由后往前的,style-loader需写在最前面
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' }
],
},
sass-loader
如果项目中用到了sass,就需要安装sass和sass-loader
安装npm install sass-loader sass webpack --save-dev
webpack5中使用sass+dart-sass 这样安装就可以了,不需要安装node-sass
在rules数组中配置规则
{
test: /\.s[ac]ss$/i,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'sass-loader' },
],
},
postcss-loader
postcss可以帮助我们自动添加浏览器前缀
安装npm install --save-dev postcss-loader postcss
安装postcss预设插件npm install postcss-preset-env -D
,它包含了自动前缀等
postcss-loader | webpack 中文文档 (docschina.org)
{
test: /\.s[ac]ss$/i,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [['postcss-preset-env']],
},
},
},
{ loader: 'sass-loader' },
],
},
asset module
项目中使用到了图片、文本等资源文件,打包时还是不能加载它们,因为还没有给它们配置loader,但从webpack5开始推出了asset module,不再需要为资源型文件配置loader,在rules数组中配置规则即可
资源模块 | webpack 中文文档 (docschina.org)
图片资源配置
{
test: /\.(png|jpe?g|gif|webp)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
// 配置资源输出位置和名称
generator: {
// 将图片文件输出到 imgs 目录中
// 将图片文件命名 [name][hash:6][ext][query]
// [name]: 之前的文件名称
// [hash:6]: hash值取6位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: 'imgs/[name][hash:6][ext][query]',
},
},
babel
babel可以帮助我们将ES6+的代码语法转换成ES5的代码
安装npm install -D babel-loader @babel/core @babel/preset-env
@babel/core
是bable的核心,@babel/preset-env
是bable的预设,因为bable的每个语法转换都需要独立的插件,如果一个个的安装,那就需要大量的插件,preset预设就直接帮我们来加载对应的插件列表
Babel 是什么? · Babel 中文网 (babeljs.cn) webpack 中文文档 (docschina.org)
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
配置插件plugins
plugin用于对webpack功能的扩展,如打包优化
HtmlWebpackPlugin
用于生成html文件,生成的文件会把项目依赖的js文件打包后加载进去
安装npm install --save-dev html-webpack-plugin
配置,插件都是对象,需要new
HtmlWebpackPlugin可以不设置参数,它会有从默认模板生成html文件
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
...
plugins: [new HtmlWebpackPlugin()],
}
也可以进行配置,使用指定的模板生成html文件,指定页面title等
// webpack.config.js
new HtmlWebpackPlugin({
title: '这里是页面标题',
template: './public/index.html',
}),
在html模板中通过<%= htmlWebpackPlugin.options.title %>
使用title
<html lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
properly without JavaScript enabled. Please enable it to
continue.
</strong>
</noscript>
</body>
</html>
DefinePlugin
DefinePlugin
允许在 编译时 将你代码中的变量替换为其他值或表达式。就是说可以定义一些全局变量,在编译时使用。
DefinePlugin
是webpack的内置插件不需要安装,导入即可
plugins: [
new HtmlWebpackPlugin({
title: '这里是页面标题',
template: './public/index.html',
}),
new DefinePlugin({
BASE_URL:'"./"'
})
],
使用变量
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
DefinePlugin | webpack 中文文档 (docschina.org)
CopyWebpackPlugin
CopyWebpackPlugin
可以帮助我们将public目录下的文件复制到dist目录下。
安装npm install copy-webpack-plugin --save-dev
导入const CopyPlugin = require('copy-webpack-plugin')
在patterns数组中配置规则,form复制的源,to复制到哪(可以省略,默认打包输出目录)
globOPtionspe进行额外配置,如ignore忽略哪些文件不复制
new CopyPlugin({
patterns: [
{
from: 'public',
globOptions: {
ignore: ['**/index.html']
}
}
]
})
集成vue
安装vuenpm install vue@next
单文件组件还需安装@vue/compiler-sfc npm install -D @vue/compiler-sfc
安装处理.vue
文件的vue-loader npm install vue-loader -D
{
test: /\.vue$/,
loader: 'vue-loader'
}
配置Vue插件
const { VueLoaderPlugin } = require('vue-loader/dist/index')
...
module.exports = {
...
plugins: [
...
new VueLoaderPlugin()
]
}
现在就可以编写.vue文件了
处理两个警告,现在打包运行后可以发现控制台会有两个警告,在DefinePlugin中进行配置
new DefinePlugin({
BASE_URL: '"./"',
__VUE_OPTIONS_API__: false, // 是否支持optionsApi
__VUE_PROD_DEVTOOLS__: false // 在生成环境是否支持devtools
}),
配置开发服务
每次进行了文件修改都需要重新build才能看到修改的效果,很麻烦,所以就需要开发服务webpack-dev-server
DevServer | webpack 中文文档 (docschina.org)
(当然也可以使用watch选项,watch 和 watchOptions | webpack 中文文档 (docschina.org))
安装npm install webpack-dev-server -D
添加scripts "serve": "webpack serve"
// package.js
"scripts": {
"build": "webpack",
"serve": "webpack serve"
},
现在运行npm run serve
就可以通过开发服务启动项目了
基础配置
如果我们想指定端口等,就需要进行一些基础配置
// webpack.config.js
devServer: {
host: "10.10.0.99", // 启动服务器域名,可以不配置或改成0.0.0.0 这样在其他ip下也可以运行
port: "3000", // 启动服务器端口号
open: true, // 是否自动打开浏览器
compress: true, // 启用gzip压缩
},
HMR
现在使用开发服务后模块内容的改变是会使打开的页面改变的了,但是它是使整改页面重新加载,而不是局部更新。使用HMR在模块改变的时候进行局部的替换更新。
模块热替换(hot module replacement) | webpack 中文文档 (docschina.org)
配置hot: true
(默认好像是开启的)
devServer: {
...
hot: true
},
这时你会发现修改vue文件、scss文件时已经实现了热更新,但是js文件却没有实现;这是因为vue-loader
、style-loader
已经帮我们实现了HMR接口,而babel-loader没有实现HMR,需要我们在导入时去判断是否开启热更新,并编写热更新发生时的回调。
// main.js
import './utils/comm.js'
if (module.hot) {
//判断是否有热加载
module.hot.accept('./utils/comm.js', function () {
//热加载的模块路径
console.log('aaa bbb!') //热加载的回调,即发生了模块更新时,执行什么 callback
})
}
代理proxy
在开发中为了解决跨域问题就需要使用proxy代理
proxy: {
'/api': {
// 匹配规则
target: 'https://other-server.example.com', // 代理目标地址
secure: false, // 接受在 HTTPS 上运行且证书无效的后端服务器
changeOrigin: true, // 服务器源跟踪
pathRewrite: { '^/api': '' } // 路径重写
}
}
解析resolve
在项目中我们导入文件的时候,发现有.js结尾的文件在导入时可以不写后缀,而.vue、.scss的不行,这些都是由webpack的解析选项设置决定的
后缀名简写的查找,当有多个同名的时候,以第一个
resolve: {
extensions: ['.js', '.json', '.vue', '.scss',...]
},
配置别名alias,比如常见的@/
resolve: {
extensions: ['.js', '.json', '.vue', '.scss'],
alias: {
'@': path.resolve(__dirname, './src')
}
},
最终的配置文件
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { DefinePlugin } = require('webpack')
const CopyPlugin = require('copy-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader/dist/index')
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'), // 用path.resolve拼接得到一个绝对路径
filename: 'js/bundle.js',
clean: true
},
resolve: {
extensions: ['.js', '.json', '.vue', '.scss'],
alias: {
'@': path.resolve(__dirname, './src')
}
},
devServer: {
host: '10.10.0.134', // 启动服务器域名,可以不配置或改成0.0.0.0 这样在其他ip下也可以运行
port: '3000', // 启动服务器端口号
open: true, // 是否自动打开浏览器
compress: true, // 启用gzip压缩
hot: true,
proxy: {
'/api': {
// 匹配规则
target: 'https://other-server.example.com', // 代理目标地址
secure: false, // 接受在 HTTPS 上运行且证书无效的后端服务器
changeOrigin: true, // 服务器源跟踪
pathRewrite: { '^/api': '' } // 路径重写
}
}
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [['postcss-preset-env']]
}
}
},
{ loader: 'sass-loader' }
]
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
}
},
// 配置资源输出位置和名称
generator: {
// 将图片文件输出到 imgs 目录中
// 将图片文件命名 [name][hash:6][ext][query]
// [name]: 之前的文件名称
// [hash:6]: hash值取6位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: 'imgs/[name][hash:6][ext][query]'
}
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
},
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: '这里是页面标题',
template: './public/index.html'
}),
new DefinePlugin({
BASE_URL: '"./"',
__VUE_OPTIONS_API__: false, // 是否支持optionsApi
__VUE_PROD_DEVTOOLS__: false // 在生成环境是否支持devtools
}),
new CopyPlugin({
patterns: [
{
from: 'public',
globOptions: {
ignore: ['**/index.html']
}
}
]
}),
new VueLoaderPlugin()
]
}
网友评论