pring Boot 微服务项目通常是通过 REST API 来提供服务的,而不是直接集成 HTML 页面。不过,今天看到有小伙伴在咨询如何在 Spring Boot 项目中集成 HTML 页面,简单整理了一下,可以采用以下常用的方法:
举例来说,如果你选择使用 Thymeleaf,可以按照以下步骤来实现:
--1 在 pom.xml 中添加以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>--2 在 application.properties 中添加以下配置:
# 配置 Thymeleaf 模板文件所在路径
spring.thymeleaf.prefix=classpath:/templates/
# 配置 Thymeleaf 模板文件后缀名
spring.thymeleaf.suffix=.html
# 配置 Thymeleaf 模板文件字符集
spring.thymeleaf.encoding=UTF-8
# 开启缓存
spring.thymeleaf.cache=true--3 在 src/main/resources/templates 目录下创建 HTML 模板文件,并使用 Thymeleaf 标签进行动态数据绑定和条件渲染等操作。
例如,以下是一个简单的 HTML 模板文件 index.html:
<!DOCTYPE html>
<html>
<head>
<title>Spring Boot + Thymeleaf</title>
</head>
<body>
<h1>Welcome to Spring Boot</h1>
<p th:text="${message}">This is a placeholder text.</p>
</body>
</html>--4 在 Spring Boot 应用程序的控制器中,使用 @GetMapping 注解定义一个返回 ModelAndView 对象的请求处理方法,并将模板文件名和动态数据传递给 ModelAndView 对象。
例如,以下是一个简单的控制器类 HomeController:
@Controller
public class HomeController {
@GetMapping("/")
public ModelAndView index() {
ModelAndView modelAndView = new ModelAndView("index");
modelAndView.addObject("message", "Hello, world!");
return modelAndView;
}
}这样,在浏览器中访问 http://localhost:8080 就可以看到渲染后的 HTML 页面了。
再举一个FreeMarker的例子来简单说一下:
当使用Spring Boot构建Web应用程序时,可以使用FreeMarker作为模板引擎来渲染HTML页面。FreeMarker是一个开源的Java模板引擎,它允许您通过定义模板来生成HTML等文档。下面是在Spring Boot项目中集成FreeMarker的一些常用方法:
--1 添加依赖:在项目的pom.xml文件中添加FreeMarker的依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>--2 配置视图解析器:在application.properties文件中添加以下配置,以告诉Spring Boot使用FreeMarker作为模板引擎来解析视图:
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.ftl--3 创建模板文件:在src/main/resources/templates目录下创建.ftl文件,该文件将用于渲染HTML页面。在模板文件中,您可以使用FreeMarker的模板语言来定义HTML页面的内容。
例如,以下是一个简单的模板文件,它将渲染一个包含“Hello World”的HTML页面:
<!DOCTYPE html>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>${message}</h1>
</body>
</html>在上面的模板中,${message}将被替换为实际的值。您可以在Java代码中使用模型来设置这个值。
--4 创建控制器:在Spring Boot应用程序中创建一个控制器,以处理HTTP请求并返回模板的名称和模型。以下是一个示例控制器:
@Controller
public class HomeController {
@GetMapping("/")
public String home(Model model) {
model.addAttribute("message", "Hello World!");
return "home";
}
}在上面的示例中,控制器返回了“home”字符串,这将作为模板文件的名称。它还将模型添加到视图中,该模型包含名为“message”的属性和“Hello World!”的值。
这是在Spring Boot项目中使用FreeMarker作为模板引擎的一些常用方法。当您使用FreeMarker时,还可以使用一些高级特性,例如条件语句、迭代器和宏,来更好地控制生成的HTML页面。
程设计是工作流的入口,开发者可以通过eclipse插件等来设计流程,但是用户并不会使用。所以可以在线设计的流程才是我们想要的,幸好activiti提供了在线设计功能,我们只需要把它集成到我们项目中就行了。
最终效果
image.png
集成Actviti
添加依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.walle</groupId>
<artifactId>activity-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>activity-service</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-boot-admin.version>2.1.1</spring-boot-admin.version>
<spring-cloud.version>Greenwich.RC2</spring-cloud.version>
<activiti.version>5.22.0</activiti.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!-- Activiti 启动器 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- Activiti 流程图 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-diagram-rest</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- Activiti 在线设计 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-modeler</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.walle</groupId>
<artifactId>common-service</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-dependencies</artifactId>
<version>${spring-boot-admin.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</project>
下载Activiti源码包
下载地址:https://www.activiti.org/get-started
解压下载的源码包后我们看到目录结构如下
创建数据库
在activiti-5.22.0/database/create 文件夹中找到对应数据库的sql文件 然后创建相关数据库。
另外,为了方便管理模型,我们才创建业务表来管理模型SQL如下
CREATE TABLE `ts_business_define` ( `business_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `business_code` varchar(100) DEFAULT NULL COMMENT '业务代码', `business_name` varchar(255) DEFAULT NULL COMMENT '业务名称', `proc_def_id` varchar(64) DEFAULT NULL COMMENT '流程定义ID', `model_id` varchar(64) DEFAULT NULL COMMENT '模型ID', `delete_status` int(11) DEFAULT '0' COMMENT '删除标记0=正常1=已删除', `create_by` bigint(20) DEFAULT '0' COMMENT '创建人', `create_byname` varchar(50) DEFAULT '0' COMMENT '创建人姓名', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `modify_by` bigint(20) DEFAULT NULL COMMENT '修改人', `modify_byname` varchar(50) DEFAULT NULL COMMENT '修改人姓名', `modify_time` datetime DEFAULT NULL COMMENT '修改时间', PRIMARY KEY (`business_id`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4;
导入静态文件
将activiti-5.22.0/war/activiti-explorer.war解压
将文件夹内 diagram-viewer,editor-app,modeler.html拷贝到项目中resource/public目录下如图
这里需要修改editor-app/app-cfg.js 来设置项目跟路径 我们设置为空就可以
ACTIVITI.CONFIG = {
// 'contextRoot' : '/activiti-explorer/service',
'contextRoot' : '',
};
导入模型相关操作Controller
解压activiti-5.22.0\libs\activiti-modeler-5.22.0-sources.jar,将StencilsetRestResource.java,
ModelEditorJsonRestResource.java,ModelSaveRestResource.java三个文件拷贝到controller目录
下载汉化文件
汉化文件,下载文件并放在resource目录下
禁用登录验证
Activiti中自动集成了security的权限验证,当我们访问接口的时候会弹出登录界面,所以我们需要禁用掉登录验证
在启动类中添加注解
@SpringBootApplication
@EnableAutoConfiguration(exclude = {
org.activiti.spring.boot.SecurityAutoConfiguration.class, org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class
})
public class ActivityServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ActivityServiceApplication.class, args);
}
}
创建模型
到此为止,我们的集成工作就基本完成了,我们可以通过浏览器访问
就可以新建一个模型了如图
模型管理
通过以上集成我们可以创建一个新的模型,然后我们会获取到一个模型ID 然后根据ID我们可以部署流程之类,现在我们通过一些简单的改造,来实现页面上对模型的操作和部署,并且和我们的业务关联起来。
业务关联模型
我们可以看到,这里需要一个模型ID的参数,我们可以把模型ID和业务定义关联起来,代码如下
@Autowired
private RepositoryService repositoryService;
@Autowired
private BusinessDefineService businessDefineService;
@PostMapping("getModelId")
public ResultResponse getModel(Long businessId, HttpServletRequest request, HttpServletResponse response) {
try {
BusinessDefine businessDefine = businessDefineService.getById(businessId);
String modelId = businessDefine.getModelId();
if (StringUtils.isBlank(modelId)) {
modelId = createModel(businessId);
}
return ResultResponse.ofSuccess(modelId);
} catch (Exception e) {
log.error("",e);
return ResultResponse.ofError(e.getMessage());
}
}
public String createModel(Long businessId) {
try {
String modelName = "modelName";
String modelKey = "modelKey";
String description = "description";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode editorNode = objectMapper.createObjectNode();
editorNode.put("id", "canvas");
editorNode.put("resourceId", "canvas");
ObjectNode stencilSetNode = objectMapper.createObjectNode();
stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
editorNode.put("stencilset", stencilSetNode);
Model modelData = repositoryService.newModel();
ObjectNode modelObjectNode = objectMapper.createObjectNode();
modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, modelName);
modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
modelData.setMetaInfo(modelObjectNode.toString());
modelData.setName(modelName);
modelData.setKey(modelKey);
//保存模型
repositoryService.saveModel(modelData);
repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8"));
BusinessDefine businessDefine = businessDefineService.getById(businessId);
businessDefine.setModelId(modelData.getId());
businessDefineService.update(businessDefine);
return modelData.getId();
} catch (Exception e) {
return null;
}
}
这里我们进行了一下判断,业务是否关联了模型,如果关联返回模型ID 如果没关联,创建一个新的模型并返回Id并关联业务
部署模型
通过业务定义获取模型,然后部署模型
/**
* 根据Model部署流程
*/
@PostMapping(value = "deploy")
public ResultResponse deploy(Long businessId) {
try {
BusinessDefine businessDefine = businessDefineService.getById(businessId);
if (StringUtils.isBlank(businessDefine.getModelId())) {
throw new SystemException("请先设计模型");
}
Model modelData = repositoryService.getModel(businessDefine.getModelId());
ObjectNode modelNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
byte[] bpmnBytes = null;
BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
bpmnBytes = new BpmnXMLConverter().convertToXML(model);
String processName = modelData.getName() + ".bpmn20.xml";
Deployment deployment = repositoryService.createDeployment().name(modelData.getName()).addString(processName, new String(bpmnBytes, "UTF-8")).deploy();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();
businessDefine.setProcDefId(processDefinition.getId());
businessDefineService.update(businessDefine);
return ResultResponse.ofSuccess();
} catch (Exception e) {
log.error("部署模型", e.getMessage(), e);
return ResultResponse.ofError(e.getMessage());
}
}
导出流程
/**
* 导出model的xml文件
*/
@GetMapping(value = "export")
public void export(Long businessId, HttpServletResponse response) {
try {
BusinessDefine businessDefine = businessDefineService.getById(businessId);
if (StringUtils.isBlank(businessDefine.getModelId())) {
throw new SystemException("请先设计模型");
}
String modelId = businessDefine.getModelId();
Model modelData = repositoryService.getModel(modelId);
BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);
ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
OutputStream outputStream = response.getOutputStream();
IOUtils.copy(in, outputStream);
String filename = bpmnModel.getMainProcess().getId() + ".bpmn.xml";
response.setHeader("content-type", "application/octet-stream");
response.setContentType("application/octet-stream;charset=UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename,"utf-8") );
outputStream.flush();
outputStream.close();
} catch (Exception e) {
log.error("导出model的xml文件失败:{}",e.getMessage(), e);
}
}
导入流程
通过xml导入流程会生成流程定义,但是不会创建模型,所以我们要通过流程定义创建模型
导入流程定义
@PostMapping("import")
public ResultResponse importXml(@RequestParam("file") MultipartFile file,Long businessId) {
try {
BusinessDefine businessDefine = businessDefineService.getById(businessId);
InputStream fileInputStream = file.getInputStream();
Deployment deployment = repositoryService.createDeployment()
.addInputStream(businessDefine.getBusinessName() +".bpmn", fileInputStream)
.deploy();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();
String modelId = changeProcessToModel(processDefinition);
businessDefine.setProcDefId(processDefinition.getId());
businessDefine.setModelId(modelId);
businessDefineService.update(businessDefine);
return ResultResponse.ofSuccess();
} catch (Exception e) {
log.error("导入流程定义失败:{}",e.getMessage(),e);
return ResultResponse.ofError(e.getMessage());
}
}
通过流程生成模型
/**
* 流程转化为可编辑模型
*
* @param processDefinition
*/
public String changeProcessToModel(ProcessDefinition processDefinition) {
Model modelData = repositoryService.newModel();
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 初始化Model
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode modelObjectNode = objectMapper.createObjectNode();
modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processDefinition.getName());
modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, processDefinition.getDescription());
modelData.setMetaInfo(modelObjectNode.toString());
modelData.setName(processDefinition.getName());
modelData.setKey(processDefinition.getKey());
// 保存模型
repositoryService.saveModel(modelData);
String deploymentId = processDefinition.getDeploymentId();
String processDefineResourceName = null;
// 通过deploymentId取得某个部署的资源的名称
List<String> resourceNames = processEngine.getRepositoryService().getDeploymentResourceNames(deploymentId);
if (resourceNames != null && resourceNames.size() > 0) {
for (String temp : resourceNames) {
if (temp.indexOf(".bpmn") > 0) {
processDefineResourceName = temp;
}
}
}
InputStream bpmnStream = processEngine.getRepositoryService().getResourceAsStream(deploymentId, processDefineResourceName);
createModelByInputStream(bpmnStream, modelData.getId());
return modelData.getId();
}
public void createModelByInputStream(InputStream bpmnStream, String ModelID) {
XMLInputFactory xif;
InputStreamReader in = null;
XMLStreamReader xtr = null;
try {
xif = XMLInputFactory.newFactory();
in = new InputStreamReader(bpmnStream, "UTF-8");
xtr = xif.createXMLStreamReader(in);
BpmnModel bpmnModel = (new BpmnXMLConverter()).convertToBpmnModel(xtr);
ObjectNode modelNode = new BpmnJsonConverter().convertToJson(bpmnModel);
repositoryService.addModelEditorSource(ModelID, modelNode.toString().getBytes("UTF-8"));
} catch (XMLStreamException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} finally {
if (xtr != null) {
try {
xtr.close();
} catch (XMLStreamException e) {
e.printStackTrace();
}
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bpmnStream != null) {
try {
bpmnStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
完!
欢迎工作一到五年的Java工程师朋友们加入Java程序员开发: 854393687
群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!
HTML Webpack Plugin这是一个webpack插件,它简化了HTML文件的创建,以服务于你的webpack bundle。这对于在文件名中包含哈希的webpack包特别有用,因为文件名会改变每次编译。您可以让插件为您生成一个HTML文件,或者使用lodash模板提供您自己的模板,或者使用您自己的加载器。
针对webpack的版本,需要安装对应不同的版本。
webpack4
npm i --save-dev html-webpack-plugin@4webpack5
npm i --save-dev html-webpack-plugin这个插件会为你生成一个HTML5文件,其中包含了使用script标签的所有webpack的bundle。
只需将插件添加到webpack配置中,如下所示:
const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = {
entry: "./src/index.js",
output: {
filename:"index_bundle.js",
path: path.resolve(__dirname,"dist")
},
plugins: [
new HtmlWebpackPlugin()
]
}这将生成一个包含以下内容的文件dist/index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Webpack App</title>
</head>
<body>
<script src="index_bundle.js"></script>
</body>
</html>如果您有多个webpack入口点,它们都将与script标签一起包含在生成的HTML中。
如果你在webpack的输出中有任何CSS资产(例如,用mini-css-extract-plugin提取的CSS),那么这些将包含在HTML头部的标签中。
如果你有使用它的插件,html-webpack-plugin应该在任何集成插件之前。
你可以传递一个配置选项到html-webpack-plugin。允许的值如下:
类型:String
默认值:Webpack App
描述:要用于生成的HTML文档的标题。
类型:String或Function
默认值:index.html
描述:要写入HTML的文件的文件名。默认为index.html。您也可以在这里指定一个子目录(例如:assets/admin.html)。占位符[name]将被条目名称替换。也可以是一个函数,例如(entryName) => entryName + '.html'。
类型:String
默认值:空
描述:默认情况下,它将使用src/index.ejs(如果存在的话)。
类型:string|Function|false
默认值:false
描述:可以用来代替模板提供一个内联模板。
类型:Boolean|Object|Function
默认值:false
描述:允许覆盖模板中使用的参数。
类型:Boolean|String
默认值:true
描述:true || 'head' || 'body' || false将所有资产注入到给定的模板或templateContent中。当传递'body'时,所有javascript资源将被放置在body元素的底部。'head'将把脚本放置在head元素中。设置为true时,将根据scriptLoading选项,决定是把脚本添加到head还是body中。使用false禁用自动注入。
类型:String|'auto'
默认值:auto
描述:publicPath属性值用于script和link 标签。
类型:blocking|defer
默认值:defer
描述:现代浏览器支持非阻塞javascript加载(“defer”),以提高页面启动性能。
类型:String
默认值:空
描述:将给定的图标路径添加到输出的HTML中。
类型:Object
默认值:{}
描述:允许注入meta标签。例如:meta: {viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'}。
类型:Object|String|false
默认值:false
描述:注入一个base标签。如base:“https://example.com/path/page.html
类型:Boolean|Object
默认值:如果mode为'production'则为true,否则为false
描述:控制是否以及以何种方式压缩输出。
类型:Boolean
默认值:false
描述:如果为true,则附加一个唯一的webpack编译哈希到所有包含的脚本和CSS文件。这对于缓存销毁是很有用的
类型:Boolean
默认值:true
描述:只有当文件被更改时,才会删除它。
类型:Boolean
默认值:true
描述:错误的详细信息将写入HTML页面。
类型:?
默认值:?
描述:只允许添加一些chunk(例如:只添加unit-test 的chunk)
类型:String|Function
默认值:auto
描述:允许控制块在包含到HTML之前应该如何排序。允许的值是'none' | 'auto' | 'manual' | {Function}。
类型:Array.<string>
默认值:空
描述:允许你跳过一些chunk(例如不添加unit-test 的chunk)。
类型:Boolean
默认值:false
描述:如果为true,则将link标签呈现为自动关闭(XHTML兼容)
下面是一个webpack配置示例,演示了如何使用这些选项:
{
entry: 'index.js',
output: {
path: __dirname + '/dist',
filename: 'index_bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
title: 'My App',
filename: 'assets/admin.html'
})
]
}要生成多个HTML文件,请在插件数组中多次声明插件。
配置示例:
{
entry: 'index.js',
output: {
path: __dirname + '/dist',
filename: 'index_bundle.js'
},
plugins: [
new HtmlWebpackPlugin(), // Generates default index.html
new HtmlWebpackPlugin({ // Also generate a test.html
filename: 'test.html',
template: 'src/assets/test.html'
})
]
}如果默认生成的HTML不能满足您的需要,您可以提供自己的模板。最简单的方法是使用template选项并传递一个定制的HTML文件。html-webpack-plugin会自动将所有必需的CSS, JS, manifest和favicon文件注入到标记中。
配置文件的部分内容:
plugins: [
new HtmlWebpackPlugin({
title: 'Custom template',
// Load a custom template (lodash by default)
template: 'index.html'
})
]模板文件index.html的内容:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
</body>
</html>如果您已经有一个模板加载器,您可以使用它来解析模板。请注意,如果您指定了html加载器并使用.html文件作为模板,也会发生这种情况。
module: {
loaders: [
{ test: /\.hbs$/, loader: "handlebars-loader" }
]
},
plugins: [
new HtmlWebpackPlugin({
title: 'Custom template using Handlebars',
template: 'index.hbs'
})
]您可以使用现成的lodash语法。如果inject特性不适合你的需要,而你又想完全控制资产的位置,可以使用html-webpack-template项目的默认模板作为你自己编写模板的起点。
*请认真填写需求信息,我们会在24小时内与您取得联系。