多页面打包#
单页面 :单个html文件 ,切换DOM的方式实现不同业务逻辑展示,后续Vue/React再拓展学习
多页面:多个html文件,切换页面实现不同业务逻辑展示
实例#
需求:把黑马头条-数据管理平台-内容页面-发布页面一起引入打包使用
步骤:
- 准备源码(html、css、js)放入相应位置,并改用模块化语法导出
- 下载form-serialize包并导入到核心代码中使用
-
配置webpack.config.js多入口和多页面的设置
// ... const config = { entry: { 模块名1: path.resolve(__dirname, 'src/入口1.js'), 模块名2: path.resolve(__dirname, 'src/入口2.js'), }, output: { path: path.resolve(__dirname, 'dist'), filename: './[name]/index.js', }, plugins: [ new HtmlWebpackPlugin({ template: './public/页面1.html', // 模板文件 filename: './路径/index.html', // 输出文件 chunks: ['模块名1'], }), new HtmlWebpackPlugin({ template: './public/页面2.html', // 模板文件 filename: './路径/index.html', // 输出文件 chunks: ['模块名2'], }), ], };
- 重新打包观察效果
内容管理页#
准备源码
将之前写的项目heima-Toutiao中的文章管理文件即page/content/index.html放入当前项目public目录下,为了避免冲突将其重命名为content.html
content.html头部引入的index.css需要自行处理,暂时取消引用
下方相对路径引入的js文件后续动态注入,先取消引入
将content页的资源文件放入src/content
content页资源request.js已有,将缺少的auth.js放入utils
接下来处理content页的index.js
首先用到了axios,所以需要导入一下(之前是login页的index.js导入了,这里页面不同另外导入)
当然,为了遵循模块化,我们从request.js中导入axios,而不是直接从node_modules中导入
模块化// content/index.js
import axios from '@/utils/request.js';
接下来看auth.js
其中也用到了axios,那么也导入一下,用到了request.js请求/响应拦截器的功能,所以也从request.js中导入
至于form-serialize插件,当前内容管理页没用到,之后发布文章再使用
注意:没有导出和导入,只是为了让目标js代码被一起打包进来,参与html最后的运行,则直接导入目标文件的路径即可
所以对于content页要用到的auth.js和content/index.css,直接在content/index.js中导入路径
import '@/utils/auth.js';
import './index.css';
设置完成,之后需要在webpack.config.js中配置新的入口
而打包出口就让webpack按照入口的名字分配,用
[name]
占位符即可
至于打包的html和css也要在插件中new新的对象,插件生成css可以使用
[name]
占位符,但是html插件不可以,而是使用chunks来区分要引入哪些打包的模块
const config = {
// entry: path.resolve(__dirname, 'src/login/index.js'),
entry: {
login: path.resolve(__dirname, 'src/login/index.js'),
content: path.resolve(__dirname, 'src/content/index.js'),
},
output: {
path: path.resolve(__dirname, 'dist'),
// filename: './login/index.js',
filename: './[name]/index.js',
clean: true,
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public/login.html'), // 模板文件
filename: path.resolve(__dirname, 'dist/login/index.html'), // 输出文件
useCdn: process.env.NODE_ENV === 'production', // 生产模式下使用cdn引入的地址
chunks: ['login'], // 引入哪些打包后的模块(和entry的key一致)
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public/content.html'), // 模板文件
filename: path.resolve(__dirname, 'dist/content/index.html'), // 输出文件
useCdn: process.env.NODE_ENV === 'production', // 生产模式下使用cdn引入的地址
chunks: ['content'],
}),
new MiniCssExtractPlugin({
filename: './[name]/index.css',
}), // 生成css文件
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
}),
],
// ...
}
最后一步,重新打包观察
运行打包后的content/index.html
未登录时先跳转到了登录页
点击登录后显示成功却未跳转,是因为在登录页的逻辑代码中跳转没加上,现在去加上再重新打包运行
document.querySelector('.btn').addEventListener('click', function () {
// 验证
// ...
({
// axios登录请求
})
.then(res => {
myAlert(true, '登录成功');
// 添加跳转逻辑及设置token
localStorage.setItem('token', res.data.token);
location.href = '../content/index.html';
})
.catch(err => {
myAlert(false, err.response.data.message);
});
console.log('提交到服务器登录...');
});
重新打包后点击登录就能正常跳转了,页面内容也显示无误
发布文章页#
需求:把发布文章页面一起打包
步骤:
- 准备发布文章页面源代码,改写成模块化的导出和导入方式
- 修改webpack.config.js的配置,增加一个入口和出口
- 打包观察效果
源码准备#
首先准备源码,之前编写的发布页publish中index.html放入当前项目public下并更名为publish.html,另外的资源文件index.css和index.js放入资源目录src/publish下
第一步来处理publish.html
头部的css文件除了我们自己编写的index.css需要引入到入口index.js中处理,其余的直接使用cdn的方式引入即可,所以先取消index.css的引入
底部的js文件:axios、form-serialize、wangeditor三个可以在生产环境下用cdn,开发环境下载本地
其余的以相对路径引入的工具包需要我们自己引入到入口js中处理,所以可以先取消引入
<%if(htmlWebpackPlugin.options.useCdn){%>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.4/axios.min.js"></script>
<script src="http://unpkg.com/form-serialize@0.7.2/index.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/wangeditor5/5.1.23/index.min.js"></script>
<%}%>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/js/bootstrap.min.js"></script>
<script src="../../utils/request.js"></script>
<script src="../../utils/editor.js"></script>
<script src="../../utils/auth.js"></script>
<script src="../../utils/alert.js"></script>
<script src="./index.js"></script>
库下载#
之后来把三个库下载到本地
axios已经下载过了,而对于另外两个:form-serialize和wangeditor,我们不确定它们用npm下载时的名字,可以去 https://www.npmjs.com/ 查找插件的名字进行下载
工具导出导入#
下载完成后往下继续,request.js每个页面都会引入,已经处理好了,跳过
editor.js放入utils,剩下的三个也已经准备好
注意导入时'@'后面不要少'/'
然后对index.js进行处理,首先要导入request.js暴露的axios
// index.js
import axios from '@/utils/request.js';
// ...
在下面的逻辑代码中需要使用wangeditor,所以在editor.js进行处理
// editor.js
// 顶部导入wangeditor
const wangEditor = require('@wangeditor/editor');
// 底部导出要暴露的editor对象
export default editor;
editor.js暴露出editor之后,index.js就可以导入以使用editor
import editor from '@/utils/editor.js';
// ...
auth.js用于判断操作权限,有无token,除了登录页都需要,所以直接在入口index.js最顶部导入即可,无需暴露什么变量
import '@/utils/auth.js';
// ...
alert.js之前使用过,采用了命名导出的方式将myAlert函数导出,入口index.js用命名方式导入即可
import { myAlert } from '@/utils/alert.js';
// ...
index.css直接导入即可
import './index.css';
// ...
补充:还有serialize函数需引入
import serialize from 'form-serialize';
// ...
webpack.config.js配置#
与内容管理页一样,设置入口-出口-插件生成页面
const config = {
// entry: path.resolve(__dirname, 'src/login/index.js'),
entry: {
login: path.resolve(__dirname, 'src/login/index.js'),
content: path.resolve(__dirname, 'src/content/index.js'),
publish: path.resolve(__dirname, 'src/publish/index.js'),
},
output: {
path: path.resolve(__dirname, 'dist'),
// filename: './login/index.js',
filename: './[name]/index.js',
clean: true,
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public/login.html'), // 模板文件
filename: path.resolve(__dirname, 'dist/login/index.html'), // 输出文件
useCdn: process.env.NODE_ENV === 'production', // 生产模式下使用cdn引入的地址
chunks: ['login'], // 引入哪些打包后的模块(和entry的key一致)
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public/content.html'), // 模板文件
filename: path.resolve(__dirname, 'dist/content/index.html'), // 输出文件
useCdn: process.env.NODE_ENV === 'production', // 生产模式下使用cdn引入的地址
chunks: ['content'],
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public/publish.html'), // 模板文件
filename: path.resolve(__dirname, 'dist/publish/index.html'), // 输出文件
useCdn: process.env.NODE_ENV === 'production', // 生产模式下使用cdn引入的地址
chunks: ['publish'],
}),
new MiniCssExtractPlugin({
filename: './[name]/index.css',
}), // 生成css文件
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
}),
],
// ...
}
配置完成,打包!
小问题 :在打包时,花费时间长,生产环境无需打包的form-serialize和wangeditor被打包了
这是因为webpack.config.js中的外部扩展我们忘记配置了,现在加上这两项再重新打包
// 生产环境下使用相关的配置
if (process.env.NODE_ENV === 'production') {
// 外部扩展(让webpack防止import的包被打包进来)
config.externals = {
// key:import from 语句后面的字符串
// value:留在原地的全局变量(最好和cdn在全局暴露的变量一致)
'bootstrap/dist/css/bootstrap.min.css': 'bootstrap',
axios: 'axios',
'form-serialize': 'serialize',
'@wangeditor/editor': 'wangEditor',
};
}
打包打包看效果!
测试功能完整