可以javascript与webpack内联吗?

时间:2016-01-23 09:14:19

标签: webpack

我需要将一个库导入到我的项目中,该库应该是一个javascript文件,需要内联到html。

例如:

库代码:

(function(){
   var a = 0;
})();

我需要在html中内联这段代码。

HTML:

<html>
  <head>
    <script>
      (function(){
         var a = 0;
      })();
    </script>
  </head>

  <body>
  </body>
</html>

我可以用webpack实现吗? 我找到了script-loader,但它运行脚本,而不是内联。

4 个答案:

答案 0 :(得分:19)

我已经开始为plugin html webpack工作以支持此功能。您指定正则表达式以匹配要嵌入内联的文件。

plugins: [
  new HtmlWebpackPlugin({
        inlineSource: '.(js|css)$' // embed all javascript and css inline
    }),
  new HtmlWebpackInlineSourcePlugin()
] 

答案 1 :(得分:8)

inline-source

的帮助下,我没有咕噜咕噜地做了
  1. 安装inline-source-cli:npm install inline-source-cli
  2. 在html文件的脚本标记中添加inline属性:<script inline src="path/to/index.js"></script>
  3. 运行inline-source --root ./dist dist/path/to/index-pre.html > dist/path/to/index.html

答案 2 :(得分:5)

最后,我们通过结合webpack和gulp来解决这个问题。 (有两个插件:gulp-html-replace和gulp-inline-source。)

HTML:

 <html>
  <head>
    <!-- build:js -->
    <!-- endbuild -->
  </head>

  <body>
  </body>
</html>

gulpfile:

  gulp.task('replace-and-inline', function () {
      return gulp.src('./dist/index.html')
        .pipe(htmlreplace({
          'js': {
            src: [your libs which you want to be inline],
            tpl: '<script src="%s" inline></script>'
          }
        }))
        .pipe(inlinesource())
        .pipe(gulp.dest('./dist/'));
    });

在package.json中,定义一个任务,它将使用webpack编译项目,然后将js文件作为内联注入。

"build": "rimraf dist && webpack --progress --hide-modules --config build/webpack.prod.conf.js;gulp replace-and-inline"

如果要发布项目,只需运行npm run build

即可

2018年7月20日更新

我们制作了一个webpack插件来解决这个问题。

https://github.com/QuellingBlade/html-webpack-inline-plugin

答案 3 :(得分:0)

对于 webpack 4,我尝试了以下 3 个插件但没有成功

  1. html-webpack-inline-plugin
  2. html-webpack-inline-source-plugin
  3. script-ext-html-webpack-plugin

然后我发现了这个 react-dev-utils/InlineChunkHtmlPlugin 所以借用它并修改以满足我的需要:

// use it like this
            ...
            new HtmlWebpackPlugin(...),
            new MiniCssExtractPlugin(...),
            new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/[.]js$/, /[.]css$/]),
            ...

// modify InlineChunkHtmlPlugin to inline both script and style
class InlineChunkHtmlPlugin {
    constructor(htmlWebpackPlugin, tests) {
        this.htmlWebpackPlugin = htmlWebpackPlugin;
        this.tests = tests;
    }

    isScript(tag) {
        return tag.tagName === 'script' && tag.attributes && tag.attributes.src;
    }

    isCss(tag) {
        return tag.tagName === 'link' && tag.attributes && tag.attributes.href && tag.attributes.rel === "stylesheet";
    }

    getInlinedTag(publicPath, assets, tag) {
        //debugger;
        const isScript = this.isScript(tag);
        const isCss = this.isCss(tag);
        if (!isScript && !isCss) {
            return tag;
        }

        const href = isScript ? tag.attributes.src : tag.attributes.href;

        const scriptName = publicPath
            ? href.replace(publicPath, '')
            : href;
        if (!this.tests.some(test => scriptName.match(test))) {
            return tag;
        }
        const asset = assets[scriptName];
        if (asset == null) {
            return tag;
        }
        return { tagName: isScript ? 'script' : 'style', innerHTML: asset.source(), closeTag: true };
    }

    apply(compiler) {
        let publicPath = compiler.options.output.publicPath || '';
        if (publicPath && !publicPath.endsWith('/')) {
            publicPath += '/';
        }

        compiler.hooks.compilation.tap('InlineChunkHtmlPlugin', compilation => {
            const tagFunction = tag =>
                this.getInlinedTag(publicPath, compilation.assets, tag);

            const hooks = this.htmlWebpackPlugin.getHooks(compilation);
            hooks.alterAssetTagGroups.tap('InlineChunkHtmlPlugin', assets => {
                assets.headTags = assets.headTags.map(tagFunction);
                assets.bodyTags = assets.bodyTags.map(tagFunction);
            });

            // Still emit the runtime chunk for users who do not use our generated
            // index.html file.
            // hooks.afterEmit.tap('InlineChunkHtmlPlugin', () => {
            //   Object.keys(compilation.assets).forEach(assetName => {
            //     if (this.tests.some(test => assetName.match(test))) {
            //       delete compilation.assets[assetName];
            //     }
            //   });
            // });
        });
    }
}