大家可以先去看我的前两篇文章,顺便可以点个三连哦,嚯嚯嚯~
webpack 之 使用 loader && babel
webpack 之 使用 plugin && mode
目录
一、开启本地服务器
1. 理由
2. 方式一 :wabpack watch
3. 方式二 :wabpack-dev-server ( 常用 )
1. 安装webpack-dev-server
2. 在package.json中配置
3. 使用npm run serve !!!!!!
4. 现在能实时更新了
二、devServer 配置 DevServer | webpack
1. static/directory :
2. HMR : 模块热替换 ( 重要 )
3. port
4. open
5. compress
6. host
7. proxy配置
三、如何区分开发环境 :优化
1. 在根目录创建config文件夹,并创建几个文件
2. 修改package.json中的配置
3. webpack.comm.config.js配置
4. webpack-merge
5. webpack.dev.config.js配置
6. webpack.prod.config.js配置
之前开发的代码,为了运行需要两个步骤
这样效率太慢了,所以希望当文件变化时,可以自动完成编译和展示
为了完成自动编译,webpack提供了几种可选的方式
在该模式下,webpack依赖图中的所有文件,只要有一个发生了更新,那么代码会被重新编译,我们不需要手动去运行npm run build
ps : 这种方式事实上本身是没有自动刷新浏览器功能的(之前是因为有live-server)
开启watch也有两种方式
这样后是不是发现下方变成了这样 ,两种方式用一个即可
wabpack-dev-server => 具备自动打包和实现监听功能
ps : 运行后并不会生成本地的文件,打包到了内存里,没有输出出来,这是为了提高效率
npm install webpack-dev-server -D
最后开发完成后,再自己npm run build一下生成打包文件即可
浏览器请求打包后的资源,如果没有请求到,会自动去这个文件夹进行查找(也就是说没有打包的资源,如果放到这个文件夹里,也能进行访问)
可以进行动态配置,因为开发阶段时如果我们也在使用CopyWebpackPlugin插件,每次运行的效率就会比较低,所以开发阶段我们可以关闭CopyWebpackPlugin直接使用这个
生产阶段的时候在打开CopyWebpackPlugin (这就涉及到动态配置了,可以使用)
总而言之 开发阶段:使用这个 | 生产阶段:CopyWebpackPlugin
devServer: {
static: {
// 指定路径
directory: path.join(__dirname, 'public')
}
}
- HMR => Hot Module Replacement,模块热替换
- 指在应用程序运行过程中,替换、添加、删除模块,而无需刷新整个页面
- 好处一 : 不重新加载整个页面,可以保留某些应用程序状态不丢失
- 好处二 : 只更新需要变化的内容,节省开发的时间
原理(理解即可)
webpack-dev-serve已经支持了HMR,我们只需要开启即可
如果不开启,当我们修改代码后,整个页面会自动刷新,使用的是live-reloading
tip : 最好同时使用target配置
// 配置服务
devServer: {
static: {
// 指定路径
directory: path.join(__dirname, 'public')
},
// 模块热替换
hot: true,
},
其实这样配置后,hot还是不生效,页面还是会刷新~,是因为引入的方式还要改,可恶
因为需要去指定哪些模块发生更新时,进行HMR
但是我们真实开发是不需要这样的,使用vue,react框架的时候,vue-loader等会自动支持hot,不需要我们自己来写,所以,我们只需要了解一下即可
port设置监听的端口,默认情况下是8080
// 配置服务
devServer: {
static: {
// 指定路径
directory: path.join(__dirname, 'public')
},
// 模块热替换
hot: true,
// 设置端口号
port: 9000,
},
open是否打开浏览器 => 默认值是false,设置为true会打开浏览器
// 配置服务
devServer: {
static: {
// 指定路径
directory: path.join(__dirname, 'public')
},
// 模块热替换
hot: true,
// 设置端口号
port: 9000,
// 是否自动打开浏览器
open: true
},
compress是否为静态文件开启gzip compression => 默认值是false
// 配置服务
devServer: {
static: {
// 指定路径
directory: path.join(__dirname, 'public')
},
// 模块热替换
hot: true,
// 设置端口号
port: 9000,
// 是否自动打开浏览器
open: true,
// 启动gzip压缩
compress: true,
},
host设置主机地址 :
localhost 和 0.0.0.0 的区别 :
devServer: {
// 模块热替换
hot: true,
// 设置端口号
port: 9000,
// 是否自动打开浏览器
open: true,
// 启动gzip压缩
compress: true,
// host配置
host: '0.0.0.0'
},
// 配置服务
devServer: {
static: {
// 指定路径
directory: path.join(__dirname, 'public')
},
// 模块热替换
hot: true,
// 启动gzip压缩,传输速率会变快
compress: true,
// 自动打开浏览器
open: true,
// 设置主机地址,默认是localhost,如果希望其他地方也可以访问,可以设置为 '0.0.0.0'
// 其他地方访问:通过你电脑的ip地址加上端口来访问的
// host: '0.0.0.0',
// 设置端口号
port: 9000,
// 配置代理,解决代理问题
proxy: {
// 当遇到'/api'的时候
'/api': {
// 将目前的地址代理至target
target: 'http://localhost:8888',
// 将'/api' 重写为''
pathRewrite: {
'^/api': ''
},
// 设置允许访问https的服务器
secure: false,
// 在某些情况下会很有用
changeOrigin: true
}
},
// 设置为true时,路由跳转如果返回了404错误,会自动返回index.html的内容
historyApiFallback: true
// 也可以设置成一个对象,根据from来匹配路径,决定跳转到哪个页面
// historyApiFallback: {
// rewrites: [
// { from: /^\/$/, to: '/views/landing.html' },
// { from: /^\/subpage/, to: '/views/subpage.html' },
// { from: /./, to: '/views/404.html' },
// ],
// },
},
优化:把开发环境和生产环境所需的各个配置分离!!!!!!
可以进行配置执行的文件
build : 打包的时候,加载生产环境所需配置
serve : 开发的时候,加载开发环境所需配置
"scripts": {
"build": "webpack --config ./config/webpack.prod.config.js",
"serve": "webpack serve --config ./config/webpack.dev.config.js"
},
const path = require('path'); // Node内置模块
// 插件的导入方式可能不同,具体查看文档哦
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 结构出来
const { DefinePlugin } = require('webpack');
module.exports = {
// 因为当前代码环境跑在web上,进行配置一下
target: 'web',
// 入口
entry: './src/index.js',
// 出口
output: {
path: path.resolve(__dirname, '../dist'), // 因为这里需要绝对路径,__dirname获取到的是当前文件所在路径,所以拼接一下
filename: 'js/boundle.js' // 打包后的js的文件名
},
// 模块解析
resolve: {
// 这些后缀名不用写
extensions: ['.js', '.json', '.vue', '.css'],
// 配置别名
alias: {
'@': path.resolve(__dirname, '../src'),
commonImg: path.resolve(__dirname, '../src/img')
// ...
}
},
// 配置模块
module: {
// 规则
rules: [
// css|less文件
{
test: /\.(css|less)$/, // 用正则表达式来进行匹配,匹配css|less文件
use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader']
},
// 图片
{
test: /\.(png|jpe?g|gif|svg)$/i, // 用正则表达式来进行匹配,匹配以这些后缀名的图片
// 自动选择
type: 'asset',
parser: {
// 数据url的条件配置
dataUrlCondition: {
// 超过100kb的图片打包,小于的弄成bast64
maxSize: 10 * 1024
}
},
// 生成
generator: {
filename: 'img/[name]__[hash:8][ext]'
}
},
// 字体文件
{
test: /\.(eot|ttf|woff2?)$/i, // 用正则表达式来进行匹配,匹配以这些后缀名的字体文件
type: 'asset/resource',
// 生成
generator: {
filename: 'font/[name]__[hash:8][ext]'
}
},
// js文件
{
test: /\.js$/,
use: ['babel-loader']
}
]
},
// 配置插件,放置着一个个的插件对象
plugins: [
// 生成index.html文件,并使用模版
new HtmlWebpackPlugin({
// 指定模版路径
template: './public/index.html',
// 顺便定义一下title
title: '超级无敌巨帅小流星'
}),
// 定义变量
new DefinePlugin({
// 这里需注意 如果只有一层引号,那么内部会去找这个变量,所以如果要写字符串的话,里面再套一层,望周知
BASE_URL: '"./"'
})
// new VueLoaderPlugin()
]
};
因为不管是生产环境,还是开发环境,都需要公共的部分,所以需要合并,合并需要一个插件
npm install webpack-merge -D
const path = require('path'); // Node内置模块
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.comm.config');
// 合并
module.exports = merge(commonConfig, {
// 设置模式
mode: 'development',
// 设置source-map,建立js映射文件,方便调试代码和错误
devtool: 'source-map',
// 配置服务
devServer: {
static: {
// 指定路径
directory: path.join(__dirname, './public')
},
// 模块热替换
hot: true,
// 启动gzip压缩,传输速率会变快
compress: true,
// 自动打开浏览器
open: true,
// 设置主机地址,默认是localhost,如果希望其他地方也可以访问,可以设置为 '0.0.0.0'
// host: '0.0.0.0',
// 设置端口号
port: 9000,
// 配置代理,解决代理问题
proxy: {
// 当遇到'/api'的时候
'/api': {
// 将目前的地址代理至target
target: 'http://localhost:8888',
// 将'/api' 重写为''
pathRewrite: {
'^/api': ''
},
secure: false,
// 在某些情况下会很有用
changeOrigin: true
}
},
// 设置为true时,路由跳转如果返回了404错误,会自动返回index.html的内容
historyApiFallback: true
}
});
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.comm.config');
// 合并
module.exports = merge(commonConfig, {
// 设置模式
mode: 'production',
plugins: [
// 自动清空dist文件夹并重新生成
new CleanWebpackPlugin(),
new CopyWebpackPlugin({
// 匹配你要复制的文件
patterns: [
{
// 入口
from: './public',
to: './public',
globOptions: {
// 忽略的文件
ignore: [
// public文件夹下所有的index.html文件都被忽略,不复制
'**/index.html'
]
}
}
]
})
]
});