webpack实现内联html css js打包

440 阅读3分钟

介绍

有时候部分页面内容是通过富文本实现,维护这个富文本也需要工程化的支持,方便解决兼容和开发规范性问题。

想法

利用webpack打包工具和插件,把html js css 合并成一个大html

方案

主要解决html,js,css 如何内容直接输出内联到一个页面里。

html 内联

方案1: 使用 inline-html-loader

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body> 
    <link href="./content.html?__inline">
</body>
</html>

方案2: 使用 raw-loader

<!DOCTYPE html>
<html lang="en">
<head> 
    <title>Document</title>
</head>
<body>
 ${ require('!raw-loader!./content.html')}
</body>
</html>

js 内联

使用 raw-loader

<!DOCTYPE html>
<html lang="en">
<head> 
    <title>Document</title>
</head>
<body>
 ${ require('!raw-loader!./content.js')}
</body>
</html>

css 内联

方案1

使用 html-inline-css-webpack-plugin

缺点:生成的css 一般只能指定到具体,依赖 mini-css-extract-plugin


const HTMLInlineCSSWebpackPlugin = require('html-inline-css-webpack-plugin').default;

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HTMLInlineCSSWebpackPlugin = require("html-inline-css-webpack-plugin").default;

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
        filename: '[name].css'
    }),
    new HtmlWebpackPlugin(),
    new HTMLInlineCSSWebpackPlugin()
  ]
}

方案2

  1. 使用raw-loader在template/html页面直接动态引入 优点,足够灵活,可以把希望插入的html js,css 放在任何一个地方。
<style>
${  require('!raw-loader!postcss-loader!less-loader!./content.less')}
</style>

注意:

style-loader加载只能在js 输出<style>内容, 下面是关于整理webpack关于css的处理总结 image.png

方案确定

由于raw-loader的灵活性,统一使用raw-loader

搭建

依赖的库

  "devDependencies": {
    "@babel/core": "^7.4.4",
    "@babel/preset-env": "^7.4.4",
    "autoprefixer": "^9.6.2",
    "babel-loader": "^8.0.5",
    "clean-webpack-plugin": "^4.0.0",
    "copy-webpack-plugin": "^5.1.2",
    "core-js": "^3.35.1",
    "css-loader": "^2.1.1",
    "file-loader": "^6.2.0",
    "html-inline-css-webpack-plugin": "^1.8.0",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.10.3",
    "less-loader": "^5.0.0",
    "mini-css-extract-plugin": "^0.6.0",
    "postcss-loader": "^3.0.0",
    "raw-loader": "^0.5.1",
    "style-loader": "^0.23.1",
    "url-loader": "^4.1.1",
    "webpack": "^4.41.0",
    "webpack-cli": "^3.3.9",
    "webpack-dev-server": "^3.11.0"
  },

目录结构介绍

image.png

src/content/ 实际开发代码

这里是自己开发的代码

detail.html

<div class="container"> 
  <h2>富文本标题</h2> 
  <section>
    <p>
      我是内容
    </p>
  </section>
</div>

detail.js

console.log("测试。。。")

detail.less

@mycolor: gray;

body {
  margin: 0;
  padding: 0;
} 
section p {
  font-size: 30px;
  color: @mycolor;
}

src/template/ 模板

核心模板文件,动态引入 html js css。

detail-all.html

<style>
${  require('!raw-loader!postcss-loader!less-loader!../content/detail.less')}
 </style>
${ require('!raw-loader!../content/detail.html')}
<script>${ require('!raw-loader!babel-loader!../content/detail.js')}</script>

这里的 postcss-loader和 babel-loader 会自动读取环境配置好了 .babelrc 和 postcss.config.js

index.html 调试的模板页面

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>模板内容</title>
  <style>
    .full-box {
      border: 1px solid red;
    }
  </style>  
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
  <h1>
    模板内容
  </h1>
  <div class="full-box" >
   
  </div>
 
  <script type="text/javascript"> 
   $(".full-box").load("detail-all.html");
  </script>
</body>
</html>

index.js

webpack打包需要的index.js 入口文件,只是为了让webpack能够正常启动,无任何其他功能。

插件plugins/

plugins/remove-main-js-plugin.js :用来删除多输出的 main.js <script>标签

const HtmlWebpackPlugin = require('html-webpack-plugin');
class RemoveMainJsPlugin {
  apply(complier) {
    //这是一个异步的钩子
      complier.hooks.emit.tapAsync("HtmlWebpackPlugin", (compilation, cb) => {
        let html = compilation.assets["detail-all.html"].source();
        html = html.replaceAll(`<script type="text/javascript" src="main.js"></script>`,"") //这里去掉引入main.js的代码
        compilation.assets["detail-all.html"] = {
          source: function () {
            // 定义文件的内容
            return html;
          },
          size: function () {
            // 定义文件的体积
            return html.length;
          },
        };
        cb();//记得要调用回调cb才能往下进入下一个钩子
      });
    }
  }
module.exports = RemoveMainJsPlugin

webpack.config.js

const path = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HTMLInlineCSSWebpackPlugin = require('html-inline-css-webpack-plugin').default;
const CopyWebpackPlugin = require("copy-webpack-plugin");
const RemoveMainJsPlugin = require("./plugins/remove-main-js-plugin");

module.exports = (env, argv) => {
  let plugins = []
  if (argv.mode === 'production') {
    plugins = plugins.concat( new CleanWebpackPlugin(
      {
        protectWebpackAssets: false,
        cleanAfterEveryBuildPatterns: ['main.js'], //删除main.js资源
      }
    ))
  }
  plugins = plugins.concat(
        new htmlWebpackPlugin({
          title: "title",
          filename: "detail-all.html",
          template: "./src/template/detail-all.html",
          minify: {
              html5: false,
              collapseWhitespace: false, //去空格
              preserveLineBreaks: false, //去换行
              minifyCSS: false,
              minifyJS: false,
              removeComments: false //去备注
          },
          templateParameters: {

          },
      }),
      new CopyWebpackPlugin([
        { from: 'src/template/index.html'},
      ]),
      new RemoveMainJsPlugin()
  )

  return {
      entry: "./src/template/index.js", //暂时不使用
      output: {
          filename: "main.js",//利⽤占位符,⽂件名称不要重复
          path: path.resolve(__dirname, "dist")//输出⽂件到磁盘的⽬录,必须是绝对路径
      },
      module: {

      },
      plugins: plugins,
      devServer: { 
        port: 9001,
      },
  };
}

通过CleanWebpackPlugin 的构子方法删除main.js文件。

 new CleanWebpackPlugin( { protectWebpackAssets: false, cleanAfterEveryBuildPatterns: ['main.js'], //删除main.js资源 } )

使用

"scripts": { 
    "dev": "webpack-dev-server --mode=development --config webpack.config.js",
    "build": "webpack --mode=production"
},

1. 安装

npm install

2. 启动开发

npm run dev

访问:http://localhost:9001/ 默认端口9001

3. 构建

npm run build

构建后的detail-all.html为最终要上传到后台的富文本内容

4. 调试

只需要启动 npm run dev调试即可 访问:http://localhost:9001/

image.png

5. 发布

只需要启动 npm run build,复制detail-all.html到后台富文本即可 查看打包效果,可以右键生成的/dist/index.html 使用live server启动查看效果。

5.1构建结果

image.png


<style>
body {
 margin: 0;
 padding: 0;
}
section p {
 font-size: 30px;
 color: gray;
}

</style>

<div class="container"> 
 <h2>富文本标题</h2> 
 <section>
   <p>
     我是内容
   </p>
 </section>
</div>

<script>console.log("测试。。。");
var a = 1;</script>

代码

github.com/mjsong07/in…

参考

github.com/cpselvis/ge…