整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          每日分享- springboot 微服務項目如何集成 html

          pring Boot 微服務項目通常是通過 REST API 來提供服務的,而不是直接集成 HTML 頁面。不過,今天看到有小伙伴在咨詢如何在 Spring Boot 項目中集成 HTML 頁面,簡單整理了一下,可以采用以下常用的方法:

          1. Thymeleaf:Thymeleaf 是一款用于在 web 和獨立環境中創建可擴展的 XML/HTML/文本模板的 Java 模板引擎。它可以輕松地與 Spring Boot 集成,使用簡單,支持模板繼承和表達式語言等功能。
          2. FreeMarker:FreeMarker 是一款基于模板的視圖渲染引擎,支持動態 HTML、XML、JSON、JavaScript、CSS 等文件的生成。它也可以輕松地與 Spring Boot 集成,使用簡單,支持模板繼承和自定義指令等功能。
          3. JSP:JSP 是一種基于 Java 技術的動態網頁開發技術,可以方便地嵌入 Java 代碼,并生成 HTML 頁面。它也可以與 Spring Boot 集成,但需要額外配置一些依賴和插件。

          舉例來說,如果你選擇使用 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@4

          webpack5

            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。允許的值如下:

          • title

          類型:String

          默認值:Webpack App

          描述:要用于生成的HTML文檔的標題。

          • filename

          類型:String或Function

          默認值:index.html

          描述:要寫入HTML的文件的文件名。默認為index.html。您也可以在這里指定一個子目錄(例如:assets/admin.html)。占位符[name]將被條目名稱替換。也可以是一個函數,例如(entryName) => entryName + '.html'。

          • template

          類型:String

          默認值:空

          描述:默認情況下,它將使用src/index.ejs(如果存在的話)。

          • templateContent

          類型:string|Function|false

          默認值:false

          描述:可以用來代替模板提供一個內聯模板。

          • templateParameters

          類型:Boolean|Object|Function

          默認值:false

          描述:允許覆蓋模板中使用的參數。

          • inject

          類型:Boolean|String

          默認值:true

          描述:true || 'head' || 'body' || false將所有資產注入到給定的模板或templateContent中。當傳遞'body'時,所有javascript資源將被放置在body元素的底部。'head'將把腳本放置在head元素中。設置為true時,將根據scriptLoading選項,決定是把腳本添加到head還是body中。使用false禁用自動注入。

          • publicPath

          類型:String|'auto'

          默認值:auto

          描述:publicPath屬性值用于script和link 標簽。

          • scriptLoading

          類型:blocking|defer

          默認值:defer

          描述:現代瀏覽器支持非阻塞javascript加載(“defer”),以提高頁面啟動性能。

          • favicon

          類型:String

          默認值:空

          描述:將給定的圖標路徑添加到輸出的HTML中。

          • meta

          類型:Object

          默認值:{}

          描述:允許注入meta標簽。例如:meta: {viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'}。

          • base

          類型:Object|String|false

          默認值:false

          描述:注入一個base標簽。如base:“https://example.com/path/page.html

          • minify

          類型:Boolean|Object

          默認值:如果mode為'production'則為true,否則為false

          描述:控制是否以及以何種方式壓縮輸出。

          • hash

          類型:Boolean

          默認值:false

          描述:如果為true,則附加一個唯一的webpack編譯哈希到所有包含的腳本和CSS文件。這對于緩存銷毀是很有用的

          • cache

          類型:Boolean

          默認值:true

          描述:只有當文件被更改時,才會刪除它。

          • showErrors

          類型:Boolean

          默認值:true

          描述:錯誤的詳細信息將寫入HTML頁面。

          • chunks

          類型:?

          默認值:?

          描述:只允許添加一些chunk(例如:只添加unit-test 的chunk)

          • chunksSortMode

          類型:String|Function

          默認值:auto

          描述:允許控制塊在包含到HTML之前應該如何排序。允許的值是'none' | 'auto' | 'manual' | {Function}。

          • excludeChunks

          類型:Array.<string>

          默認值:空

          描述:允許你跳過一些chunk(例如不添加unit-test 的chunk)。

          • xhtml

          類型: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文件

          要生成多個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項目的默認模板作為你自己編寫模板的起點。


          主站蜘蛛池模板: 免费一区二区三区在线视频| 亚洲中文字幕一区精品自拍| 国产福利一区二区三区在线观看| 日韩精品一区在线| 精品无码国产一区二区三区AV| 国产日韩精品一区二区在线观看| 亚洲视频免费一区| 久久无码人妻一区二区三区 | 爱爱帝国亚洲一区二区三区| 91久久精品一区二区| 日韩精品一区二区三区大桥未久 | 中文字幕一区二区三区日韩精品| 久久精品日韩一区国产二区| 91精品一区二区三区在线观看| 国产波霸爆乳一区二区| 国精品无码一区二区三区在线| 久久一区二区免费播放 | 精品人妻无码一区二区色欲产成人| 亚洲av无码一区二区乱子伦as| 亚洲乱码日产一区三区| 国产在线精品一区二区在线观看 | 亚洲av乱码中文一区二区三区| 精品国产a∨无码一区二区三区| 亚洲国产一区在线| 3d动漫精品一区视频在线观看| 亚洲一区二区三区高清| 亚洲狠狠狠一区二区三区| 久久精品无码一区二区WWW| 91精品乱码一区二区三区| 国产成人精品第一区二区| 亚洲sm另类一区二区三区| 一色一伦一区二区三区| 亚洲码欧美码一区二区三区| 无码少妇A片一区二区三区| 日韩精品国产一区| 精品日韩在线视频一区二区三区| 日韩人妻无码一区二区三区| 日韩精品无码一区二区三区 | 国产成人一区二区三区在线观看| 国产成人久久精品一区二区三区 | 日韩视频免费一区二区三区|