Git Product home page Git Product logo

html-webpack-inline-source-plugin's People

Contributors

andybarron avatar anion155 avatar callumacrae avatar dominikpalo avatar dustinjackson avatar eterion avatar ggd543 avatar kdepp avatar lcjnil avatar mik30s avatar pluma avatar wingrunr21 avatar wulijian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

html-webpack-inline-source-plugin's Issues

An option to drop inlined resources

Since resources are already inlined, probably, there is no need to have them in the drop folder anymore. Could we have such an option, please?

TypeError: Cannot read property 'source' of undefined

I must be missing something very basic here:

webpack.config.js:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');

module.exports = {
    entry: './src/app.js',
    output: {
        filename: './dist/bundle.js',
    },
    plugins: [
        new HtmlWebpackPlugin({
            inlineSource: '.(js)$'
        }),
        new HtmlWebpackInlineSourcePlugin(),
    ]
};

./src/app.js:

import bus from 'framebus';
import Cookies from "js-cookie";

console.log('hum..');

Build error:

ERROR in   TypeError: Cannot read property 'source' of undefined

  - index.js:52 HtmlWebpackInlineSourcePlugin.resolveSourceMaps
    [iframe-cookie-reader]/[html-webpack-inline-source-plugin]/index.js:52:22

  - index.js:113 HtmlWebpackInlineSourcePlugin.processTag
    [iframe-cookie-reader]/[html-webpack-inline-source-plugin]/index.js:113:30

  - index.js:45
    [iframe-cookie-reader]/[html-webpack-inline-source-plugin]/index.js:45:20

  - Array.forEach

  - index.js:44 HtmlWebpackInlineSourcePlugin.processTags
    [iframe-cookie-reader]/[html-webpack-inline-source-plugin]/index.js:44:19

  - index.js:25 Compilation.<anonymous>
    [iframe-cookie-reader]/[html-webpack-inline-source-plugin]/index.js:25:25

  - Tapable.js:272 Compilation.applyPluginsAsyncWaterfall
    [iframe-cookie-reader]/[tapable]/lib/Tapable.js:272:13

  - util.js:16 Compilation.tryCatcher
    [iframe-cookie-reader]/[bluebird]/js/release/util.js:16:23


  - index.js:645
    [iframe-cookie-reader]/[html-webpack-plugin]/index.js:645:12

  - index.js:151
    [iframe-cookie-reader]/[html-webpack-plugin]/index.js:151:16

  - util.js:16 tryCatcher
    [iframe-cookie-reader]/[bluebird]/js/release/util.js:16:23

  - promise.js:512 Promise._settlePromiseFromHandler
    [iframe-cookie-reader]/[bluebird]/js/release/promise.js:512:31

  - promise.js:569 Promise._settlePromise
    [iframe-cookie-reader]/[bluebird]/js/release/promise.js:569:18

  - promise.js:614 Promise._settlePromise0
    [iframe-cookie-reader]/[bluebird]/js/release/promise.js:614:10

  - promise.js:693 Promise._settlePromises
    [iframe-cookie-reader]/[bluebird]/js/release/promise.js:693:18

  - async.js:133 Async._drainQueue
    [iframe-cookie-reader]/[bluebird]/js/release/async.js:133:16

  - async.js:143 Async._drainQueues
    [iframe-cookie-reader]/[bluebird]/js/release/async.js:143:10

  - async.js:17 Immediate.Async.drainQueues [as _onImmediate]
    [iframe-cookie-reader]/[bluebird]/js/release/async.js:17:14

not working for woff, ttf files

Does this work for woff, ttf files? I have the following settings:

inject: false,
inlineSource: '.(woff|ttf)$',
template: './src/index.html'

I get errors from some these files when I load the bundle on a subroute

[Feature Request] Inline favicon

A favicon can be declared like
<link rel="icon" href="/favicon.ico">

Currently the plugin would treat this as css and output it as <style></style> instead of <link rel="icon" href="base64encoded:icon">

It would be nice to have this feature

Upgrade to html-webpack-plugin 4

The html-webpack-plugin version 4 is getting closer to a release.
Many information can be found in this pr: jantimon/html-webpack-plugin#953

A static version property was added:
https://github.com/jantimon/html-webpack-plugin/blob/d65b37d2c588047e0d81a38f4645fcdb3ead0b9e/index.js#L915-L927

The event system was changed alot to work with the new features:

Could you please give the new events a try and let me know if they work for your case?
https://github.com/jantimon/html-webpack-plugin/tree/webpack-4#events

beforeAssetTagGeneration hook

    AsyncSeriesWaterfallHook<{
      assets: {
        publicPath: string,
        js: Array<{string}>,
        css: Array<{string}>,
        favicon?: string | undefined,
        manifest?: string | undefined
      },
      outputName: string,
      plugin: HtmlWebpackPlugin
    }>

alterAssetTags hook

    AsyncSeriesWaterfallHook<{
      assetTags: {
        scripts: Array<HtmlTagObject>,
        styles: Array<HtmlTagObject>,
        meta: Array<HtmlTagObject>,
      },
      outputName: string,
      plugin: HtmlWebpackPlugin
    }>

alterAssetTagGroups hook

    AsyncSeriesWaterfallHook<{
      headTags: Array<HtmlTagObject | HtmlTagObject>,
      bodyTags: Array<HtmlTagObject | HtmlTagObject>,
      outputName: string,
      plugin: HtmlWebpackPlugin
    }>

afterTemplateExecution hook

    AsyncSeriesWaterfallHook<{
      html: string,
      headTags: Array<HtmlTagObject | HtmlTagObject>,
      bodyTags: Array<HtmlTagObject | HtmlTagObject>,
      outputName: string,
      plugin: HtmlWebpackPlugin,
    }>

beforeEmit hook

    AsyncSeriesWaterfallHook<{
      html: string,
      outputName: string,
      plugin: HtmlWebpackPlugin,
    }>

afterEmit hook

    AsyncSeriesWaterfallHook<{
      outputName: string,
      plugin: HtmlWebpackPlugin
    }>

Can this plugin emit the Automatic Refresh when using `webpack-dev-server --hot`?

Hi @DustinJackson ~ I am very excited to use html-webpack-inline-source-plugin to build my bunldle, but there is a problem confused me a lot. I use html-webpack-inline-source-plugin as below, and when I start thiswebpack.config.js by webpack-dev-server -d --content-base dist/ --hot, it can't emit the Automatic Refresh, whereas withouthtml-webpack-inline-source-plugin it does . Looking forward to your reply.

var webpack = require('webpack');
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var autoprefixer = require('autoprefixer');

module.exports = {
    entry: {
        index:"./src/js/index.js"
    },
    output: {
        path: "./dist/",
        filename: "js/[name].js",
        chunkFilename: "js/[name].js"
    },
    module: {
        preLoaders: [
            {
                test: /\.js$/,
                loader: 'eslint',
                exclude: /node_modules/
            }
        ],
        loaders: [
            {
                test: /\.less$/,
                loader: ExtractTextPlugin.extract([
                        'css-loader?modules&importLoaders=1&localIdentName=[local]___[hash:base64:5]',
                        'postcss-loader', 
                        'less-loader'
                    ])
            },
            {
                test: /\.(jpe?g|png|gif|svg)$/i,
                loaders: [
                    'url?limit=5012&name=./static/images/[name]_[hash].[ext]'
                ]
            },
            {
                test: /\.html$/,
                loader: 'html'
            },
            {
                test: /\.(ejs|tpl|tmpl)$/,
                loader: 'ejs'
            },
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: "babel-loader"
            }
        ]
    },
    postcss: function () {
        return [autoprefixer];
    },
    plugins: [
        new ExtractTextPlugin('style.css'),
        new HtmlWebpackPlugin({
            title: 'title',
            template: './src/index.html', 
            filename: './index.html', 
            inject: true,
            inlineSource:  '.(js|css)$',
            minify: {
                removeComments: true,
                collapseWhitespace: true
            },
            chunks: ["index"]
        }),
        new HtmlWebpackInlineSourcePlugin()
    ]
};

If inlined source has sourceMaps, then following lines will be broken

e.g.

<script src="A" /><script src="B" /><script src="C" /> If I want to inline A script which has source maps, then above scripts will become <script> A script contents **//# sourceMappingUrl=[url] </script><script src="B" /><script src="C" />**

Note B and C scripts are ignored because of the leading //# for source maps

add an option: inlineSize?

if assets size is smaller than the given size value, then inline the assets matched.
just like below:

chunk.files.forEach(function(name) {
      if (/\.(js|css)$/.test(name)) {
      var asset = compilation.assets[name];
      if (asset && typeof asset.size === 'function' && asset.size() <= inlineSize) {
        chunkFiles.push(name);
      }
    }
});

sourceMappingURL broken when using URL in publicPath

Example webpack configuration:

import path from 'path'
import webpack from 'webpack'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import InlineSourcePlugin from 'html-webpack-inline-source-plugin'

export default {
  context: path.resolve(__dirname, 'src'),

  entry: ['./index.js'],

  devtool: 'source-map',

  output: {
    publicPath: `https://my.cdn.com`,
    filename: '[name].[contenthash].js',
    path: path.resolve(__dirname, 'dist'),
  },

  optimization: {
    runtimeChunk: 'single',
    splitChunks: {
      cacheGroups: {
        vendors: false,
        vendor: {
          name: 'vendor',
          chunks: 'initial',
          test: /node_modules/,
          priority: 20,
        },
      },
    },
  },

  plugins: [
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    new HtmlWebpackPlugin({
      inlineSource: 'runtime.+\\.js',
    }),
    new InlineSourcePlugin(),
  ],

  resolve: {
    extensions: ['.js', '.jsx', '.scss'],
    modules: [
      path.resolve(__dirname, 'src'),
    ],
  },
}

Output index.html:

...
//# sourceMappingURL=https:/my.cdn.com/runtime.9a39f8dda0e7ff95bb67.js.map</script>

Note the single slash after https:

[REQUEST] Option to put the <style> tag in the <body>

I'm currently working on a project which limits my options with the content in the <head> tag, so I'm forced to put the <style> tag in the <body> (at the top).

Is there any way this could be implemented? Alternatively, is there any other solution to this?

What command to run

I'm extremely new to react and webpack.
I did all the instructions that the readme.md says: edited my-app/node_modules/react-scripts/config/webpack.config.js according the instructions.
and now what? Should i run a certain command on the terminal in order to create the desired build?

Removing asset tags

Hi, thanks for the plugin and it works as intended (assets are inlined nicely), but for some reason
the script and link tags are kept in the resulting markup. Any way to remove them via this plugin or a common process that's used to remove them?

sourceMappingURL is incorrect when using an actual URL

My bundle has a comment at the end:

//# sourceMappingURL=https://example.com/app.5af3ef84a94002c0fd06.js.map

After inlining the comment is rewritten as follows:

//# sourceMappingURL=/https:/example.com/app.5af3ef84a94002c0fd06.js.map

This is clearly wrong. The plugin should treat the source URL as an actual URL.

Cannot read property 'tapAsync' of undefined

I added this plugin to the webpack configuration ejected from my React app (created using the create-react-app toolkit) and now every attempt to build the app fails with an error:

Cannot read property 'tapAsync' of undefined

Webpack version: 4.19.1
HTML webpack plugin version: 4.0.0-alpha.2

Plugins sonfiguration:

  plugins: [
    // Generates an `index.html` file with the <script> injected.
    new HtmlWebpackPlugin({
      inject: true,
      template: paths.appHtml,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
        useShortDoctype: true,
        removeEmptyAttributes: true,
        removeStyleLinkTypeAttributes: true,
        keepClosingSlash: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true,
      },
      inlineSource: '.(js|css)$' // embed all javascript and css inline
    }),
    new HtmlWebpackInlineSourcePlugin(),
    // Inlines the webpack runtime script. This script is too small to warrant
    // a network request.
    shouldInlineRuntimeChunk &&
      new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime~.+[.]js/]),
    // Makes some environment variables available in index.html.
    // The public URL is available as %PUBLIC_URL% in index.html, e.g.:
    // <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
    // In production, it will be an empty string unless you specify "homepage"
    // in `package.json`, in which case it will be the pathname of that URL.
    new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
    // This gives some necessary context to module not found errors, such as
    // the requesting resource.
    new ModuleNotFoundPlugin(paths.appPath),
    // Makes some environment variables available to the JS code, for example:
    // if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
    // It is absolutely essential that NODE_ENV was set to production here.
    // Otherwise React will be compiled in the very slow development mode.
    new webpack.DefinePlugin(env.stringified),
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: 'static/css/[name].[contenthash:8].css',
      chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
    }),
    // Generate a manifest file which contains a mapping of all asset filenames
    // to their corresponding output file so that tools can pick it up without
    // having to parse `index.html`.
    new ManifestPlugin({
      fileName: 'asset-manifest.json',
      publicPath: publicPath,
    }),
    // Moment.js is an extremely popular library that bundles large locale files
    // by default due to how Webpack interprets its code. This is a practical
    // solution that requires the user to opt into importing specific locales.
    // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
    // You can remove this if you don't use Moment.js:
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    // Generate a service worker script that will precache, and keep up to date,
    // the HTML & assets that are part of the Webpack build.
    new WorkboxWebpackPlugin.GenerateSW({
      clientsClaim: true,
      exclude: [/\.map$/, /asset-manifest\.json$/],
      importWorkboxFrom: 'cdn',
      navigateFallback: publicUrl + '/index.html',
      navigateFallbackBlacklist: [
        // Exclude URLs starting with /_, as they're likely an API call
        new RegExp('^/_'),
        // Exclude URLs containing a dot, as they're likely a resource in
        // public/ and not a SPA route
        new RegExp('/[^/]+\\.[^/]+$'),
      ],
    }),
    // TypeScript type checking
    fs.existsSync(paths.appTsConfig) &&
      new ForkTsCheckerWebpackPlugin({
        typescript: resolve.sync('typescript', {
          basedir: paths.appNodeModules,
        }),
        async: false,
        checkSyntacticErrors: true,
        tsconfig: paths.appTsConfig,
        compilerOptions: {
          module: 'esnext',
          moduleResolution: 'node',
          resolveJsonModule: true,
          isolatedModules: true,
          noEmit: true,
          jsx: 'preserve',
        },
        reportFiles: [
          '**',
          '!**/*.json',
          '!**/__tests__/**',
          '!**/?(*.)(spec|test).*',
          '!src/setupProxy.js',
          '!src/setupTests.*',
        ],
        watch: paths.appSrc,
        silent: true,
        formatter: typescriptFormatter,
      }),
  ].filter(Boolean),

incorrect readme - HtmlWebpackInlineSourcePlugin does not accept any options

as said at https://github.com/DustinJackson/html-webpack-inline-source-plugin , I did:

// vue.config.js from vue cli 3.0 app
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');

module.exports = {
    configureWebpack: {
        plugins: [
            new HtmlWebpackPlugin({
                inlineSource: '\.css$'
            }),
            new HtmlWebpackInlineSourcePlugin(HtmlWebpackPlugin)
        ]
    }
};

got error: "The HtmlWebpackInlineSourcePlugin does not accept any options" - from plugin's index.js

function HtmlWebpackInlineSourcePlugin (options) {
  assert.equal(options, undefined, 'The HtmlWebpackInlineSourcePlugin does not accept any options');
}

fixed to

   ...
            new HtmlWebpackInlineSourcePlugin()
   ...

all works.

Delete the inlined files

When I've inlined a file into my HTML document, I no longer need that file in the dist folder. It would be nice if this plugin included an option to automatically delete that file from the dist folder.

Custom tag attributes

What do you think about adding a new feature, which allow you to add custom attributes to inline <script> tags?

Sourcemap TypeError: code.match is not a function

Anyone getting this error?

- source-map-url.js:35 Object.getFrom
    [my-project]/[source-map-url]/source-map-url.js:35:24
  
  - index.js:57 HtmlWebpackInlineSourcePlugin.resolveSourceMaps
    [my-project]/[html-webpack-inline-source-plugin]/index.js:57:37
  
  - index.js:112 HtmlWebpackInlineSourcePlugin.processTag
    [my-project]/[html-webpack-inline-source-plugin]/index.js:112:30
  
  - index.js:45 
    [my-project]/[html-webpack-inline-source-plugin]/index.js:45:20
  
  - Array.forEach
  
  - index.js:44 HtmlWebpackInlineSourcePlugin.processTags
    [my-project]/[html-webpack-inline-source-plugin]/index.js:44:19

I'm using devtool: 'cheap-module-source-map'

and my Plugin config looks like this:

  new HtmlWebpackPlugin({
    template: 'src/app/index.html',
    inject: 'body',
    favicon: 'src/app/favicon.png',
    inlineSource: ENV_PROD ? '(vendor)|(my\.app)' : ''
  }),

It looks like it's coming from:

// Extract original sourcemap URL from source string
var mapUrlOriginal = sourceMapUrl.getFrom(source);

Not working with webpack 4

I followed all instructions provided online but in my webpack confgi file I have this

[Could not find a declaration file for module 'html-webpack-inline-source-plugin'. 'c:/custom-xammp/htdocs/videomill-dashboard/node_modules/html-webpack-inline-source-plugin/index.js' implicitly has an 'any' type. Try npm install @types/html-webpack-inline-source-pluginif it exists or add a new declaration (.d.ts) file containingdeclare module 'html-webpack-inline-source-plugin';ts(7016)](url)

What do I need to do to solve this problem?

regex syntax?

Not sure what the regex to match a specific file is supposed to be.

My config is essentially:

  context: __dirname,
  entry: [
    './public/js/app.js',
    './public/js/form.js',
    'webpack-dev-server/client',
  ],
  devServer: {
    contentBase: './public',
    watchContentBase: true,
    port: 3006,
  },
  output: {
    path: path.resolve(__dirname, 'public'),
    publicPath: '/',
    filename: 'bundle.js',
  },

...
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, 'public/index.html'),
      // inject: true,
      inlineSource: 'form.js'
    }),
    new HtmlWebpackInlineSourcePlugin()
...

I don't want to embed everything, so this won't work: '.(js|css)$'

But nothing seems to be capturing just the "form" (tried several patterns). What am I doing wrong?

Sourcemap URLs break when inlined

Issue

By default, Webpack generates sourcemap URLs relative to the output file.

dist/
   index.html
   scripts/
      bundle.js
      bundle.js.map

Sourcemap URL: 'bundle.js.map' 
Relative to 'bundle.js', resolves to URL '/scripts/bundle.js.map'
OK!

Once we inline the output file, the sourcemaps will be loaded relative to the HTML file, which may not work:

dist/
   index.html
   scripts/
      bundle.js
      bundle.js.map

Sourcemap URL: 'bundle.js.map' 
Relative to 'index.html', resolves to URL '/bundle.js.map'
NOT FOUND! :(

Even with source and maps in the top-level dist/ directory, sourcemaps won't work properly for URL paths when using HTML5 history routing:

dist/
   index.html
   bundle.js
   bundle.js.map

Route 'some/route' serves 'index.html'
Sourcemap URL: 'bundle.js.map'
Relative to 'some/route', resolves to URL '/some/route/bundle.js.map'
NOT FOUND! :(

Solution

When inlining the JS, we should change the source map URL to be relative to the Webpack output.publicPath option.

dist/
   index.html
   scripts/
      bundle.js
      bundle.js.map

Sourcemap URL: '/scripts/bundle.js.map' 
Absolute URL served from 'dist/' will correctly resolve to sourcemap file
FIXED! :)

What is this plugin supposed to do?

I am under the impression that this is what you expect:

myProject/
- src/
- - utils.js
- - static/
- - - - index.html
- webpack.config.js

src/index.html

<html>
  <script src='./utils.js'></script>
  <body>
  </body>
</html>

src/utils.js

function doStuff() {
  console.log('doing so much stuff.');
}

webpack.config.js

...
    new HtmlWebpackPlugin({
      template: path.join(STATIC_ASSETS_DIR, 'index.html'),
      hash: false,
      // Don't inject main.js, etc
      inject: false,
      inlineSource: '.(js)$',
      filename: 'index.html',
      minify: {
        collapseWhitespace: true
      }
    }),
    new HtmlWebpackInlineSourcePlugin()
...

And then when you run webpack, you expect

dist/index.html

<html>
  <script>
    function doStuff() {
      console.log('doing so much stuff.');
    }
  </script>
  <body>
  </body>
</html>

Is this not what this plugin is supposed to do?

TypeError: Path must be a string. Received undefined

 ERROR in   TypeError: Path must be a string. Received undefined

      - index.js:110 HtmlWebpackInlineSourcePlugin.processTag
        [street]/[html-webpack-inline-source-plugin]/index.js:110:32

      - index.js:45
        [street]/[html-webpack-inline-source-plugin]/index.js:45:20

      - Array.forEach

      - index.js:44 HtmlWebpackInlineSourcePlugin.processTags
        [street]/[html-webpack-inline-source-plugin]/index.js:44:19

      - index.js:25 Compilation.<anonymous>
        [street]/[html-webpack-inline-source-plugin]/index.js:25:25

      - Tapable.js:135 Compilation.applyPluginsAsyncWaterfall
        [street]/[tapable]/lib/Tapable.js:135:13

      - util.js:16 Compilation.tryCatcher
        [street]/[bluebird]/js/release/util.js:16:23


      - index.js:627
        [street]/[html-webpack-plugin]/index.js:627:12

      - index.js:150
        [street]/[html-webpack-plugin]/index.js:150:16

      - util.js:16 tryCatcher
        [street]/[bluebird]/js/release/util.js:16:23

      - promise.js:510 Promise._settlePromiseFromHandler
        [street]/[bluebird]/js/release/promise.js:510:31

      - promise.js:567 Promise._settlePromise
        [street]/[bluebird]/js/release/promise.js:567:18

      - promise.js:612 Promise._settlePromise0
        [street]/[bluebird]/js/release/promise.js:612:10

      - promise.js:691 Promise._settlePromises
        [street]/[bluebird]/js/release/promise.js:691:18

      - async.js:138 Async._drainQueue
        [street]/[bluebird]/js/release/async.js:138:16

      - async.js:148 Async._drainQueues
        [street]/[bluebird]/js/release/async.js:148:10

      - async.js:17 Immediate.Async.drainQueues
        [street]/[bluebird]/js/release/async.js:17:14

Inline css twice in Vue-CLI 3 with html-webpack-inline-source-plugin

Expected behavior

Size of my css file is 13.8kb, html is 2.8kb. So I wanna that my css file can be inlined with html-webpack-inline-source-plugin.

Current behavior

The size of my html file increased to 30.4kb
And I found that my css file was inlined twice.

Config

Adding this plugin by webpack-chain API

// vue.config.js
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin')
module.exports = {
    chainWebpack: config => {
        config.plugin('html').tap(args => {
            args[0].inlineSource = '.css$'
            return args
        }
        config.plugin('inline').use(HtmlWebpackInlineSourcePlugin)
    }
}

When I inspecting my project's webpack config
vue inspect > output.js

// output.js
/* config.plugin('html') */
new HtmlWebpackPlugin(
  {
    templateParameters: function () { /* omitted long function */ },
    template: '/Users/logan/tencent/qgact/src/index.html',
    filename: 'index.html',
    inlineSource: '.css$'
  }
),
/* config.plugin('inline') */
new HtmlWebpackInlineSourcePlugin()

Enviroment

Node.js 10.9.0
@vue/cli-service 3.0.0
webpack 4.15.1
html-webpack-plugin 3.2.0
html-webpack-inline-source-plugin 0.0.10

TypeError: Cannot read property 'source' of undefined

Hi! When I try to build my project using v1.0.0-beta.2 of this plugin, html-webpack-plugin v4.0.0-beta.4 and webpack v4.27.0, I'm getting the following error:

  TypeError: Cannot read property 'source' of undefined
  - index.js:53 HtmlWebpackInlineSourcePlugin.resolveSourceMaps
    [web-service-main]/[html-webpack-inline-source-plugin]/index.js:53:22

  - index.js:122 HtmlWebpackInlineSourcePlugin.processTag
    [web-service-main]/[html-webpack-inline-source-plugin]/index.js:122:30

  - index.js:42
    [web-service-main]/[html-webpack-inline-source-plugin]/index.js:42:24

  - Array.forEach

  - index.js:41 HtmlWebpackInlineSourcePlugin.processTags
    [web-service-main]/[html-webpack-inline-source-plugin]/index.js:41:23

  - index.js:25 self.htmlWebpackPlugin.getHooks.alterAssetTagGroups.tapAsync
    [web-service-main]/[html-webpack-inline-source-plugin]/index.js:25:27

  - new Promise

  - Hook.js:154 AsyncSeriesWaterfallHook.lazyCompileHook
    [web-service-main]/[tapable]/lib/Hook.js:154:20

  - index.js:237 assetsPromise.then.then
    [web-service-main]/[html-webpack-plugin]/index.js:237:79

It looks like something is wrong with looking up assets. I'm using multiple entries and I've got multiple calls to html-webpack-plugin - I'm generating separate index.html for each language that we support.

The keys in compilation.assets are e.g.:

'assets/main/css/pt.2c4059d6.chunk.css',
'assets/main/css/ru.2c4059d6.chunk.css',
'assets/main/css/tr.2c4059d6.chunk.css',

Taking 'assets/main/css/tr.2c4059d6.chunk.css' as an example, when this plugin is disabled, the generated link tag looks like this:

<link href="/assets/main/css/tr.2c4059d6.chunk.css" rel="stylesheet">

When this plugin is enabled, in the processTag method:

  • publicUrlPrefix has value of '/'
  • filename has value of tr/index.html
  • assetUrl has initially the correct value of 'assets/main/css/tr.2c4059d6.chunk.css'
  • but later it's modified to 'tr//assets/main/css/tr.2c4059d6.chunk.css'
  • assetName has value of Users/.../web-service-main/tr/assets/main/css/tr.2c4059d6.chunk.css.

Thus, the check if (processedKey === assetName) in getAssetByName function always fails and the function returns undefined instead of an asset.

If I remove this code:

// if filename is in subfolder, assetUrl should be prepended folder path
if (path.basename(filename) !== filename) {
  assetUrl = path.dirname(filename) + '/' + assetUrl;
}

it seems to work correctly.

Javascript file still in dist folder

I added your sample from the readme to my webpack config file. And the javascript is now inlined in my html (as requested)

But the javascript file also still is in my dist folder (which is no longer needed) is there a flag or so that the used javascript file is removed?

Thanks

sourceMappingURL is broken when webpack.SourceMapDevToolPlugin is used

If a custom config for the webpack.SourceMapDevToolPlugin is used and the output.publicPath is set in the webpack config, the logic that adjusts the source map url breaks it:

Configuration

const { SourceMapDevToolPlugin } = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const HtmlWebpackInlineSourcePlugin = require("html-webpack-inline-source-plugin");

module.exports = {
  devtool: false,
  output: {
    publicPath: "/foo/bar"
  },
  plugins: [
    new HtmlWebpackPlugin({ inlineSource: ".(js|css)$" }),
    new HtmlWebpackInlineSourcePlugin(),
    new SourceMapDevToolPlugin({
      filename: "[file].map",
      append: `\n//# sourceMappingURL=https://example.com/[file].map`
    })
  ]
};

Current Output

//# sourceMappingURL=/foo/bar/https:/example.com/main.js.map

Expected Output

//# sourceMappingURL=https://example.com/main.js.map

Reproduction repo: https://github.com/gribnoysup/html-webpack-inline-source-plugin-with-custom-sourcemap

Looking at the initial issue and the PR that introduced this sourceMappingURL processing, seems like it will in general work only with the assumption that your index.html and all the other assets are served from the same domain and with the same folder structure for the assets, so it would be nice to be able to opt out as this is not the only case possible especially with the more custom webpack configurations.

can this be used with a react app?

I'm very new to this, apologies if this is a silly question but I'm quite lost.

I want to create a react app in a single html file. Is it possible?

it doesn't work for me

it doesn't work for me with this configuration:

var HtmlWebpackPlugin = require('html-webpack-plugin');
var HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
const path = require('path');
module.exports = {
    entry: './index.js',
    output: {
        path: "dist",
        filename: 'bundle.js'
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: "index.html",
            hash: true,
            favicon: "./pic/123.jpg",
            inject: "head",
            title: "sth",
            inlineSource: '.(js|css)$',
        }),
        new HtmlWebpackInlineSourcePlugin(),
    ]
}

causing error if script file is in relative path

webpack run causes the error.
webpack version is 2.3.2.

Error message:

ERROR in TypeError: Cannot read property 'source' of undefined

  • index.js:52 HtmlWebpackInlineSourcePlugin.resolveSourceMaps
    [xxxxxx]/[html-webpack-inline-source-plugin]/index.js:52:21

related part of webpack.config.js

plugins: [
new HtmlWebpackPlugin({
template: 'src/static/index.html',
inject: 'true',
filename: 'index.html',
inlineSource: '.(js|css)$', // embed all javascript and css inline
}),
new HtmlWebpackInlineSourcePlugin(),
]

quick fix is to modify the end of processTag() as:

if (assetUrl) {
// Strip query string (e.g. cache busting hash) from asset URL
assetUrl = assetUrl.replace(/?.*$/, '');
// Strip public URL prefix from asset URL to get Webpack asset name
var assetName =
(compilation.outputOptions.publicPath) ?
path.posix.relative(publicUrlPrefix, assetUrl) :
assetUrl;
var asset = compilation.assets[assetName];
var updatedSource = this.resolveSourceMaps(compilation, assetName, asset);
tag.innerHTML = updatedSource;
}

This is just a quick fix and I'm not sure this is appropriate.

if HtmlWebpackPlugin's config make inject false

if HtmlWebpackPlugin's config make inject to false, how to make inline-source-plugin work.

like this:

new HtmlWebpackPlugin({
      filename,
      template,
      chunks: ["index"],
      inject: false,
      inlineSource: '.(js|css)$'
    })

template:

<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
  <script type="text/javascript" src="<%= htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>
<% } %>

when pack process end, I get this:

<script type="text/javascript" src="/js/index.3a913471.js"></script>

finally, if I make inject false => true, I will get this:

<script>
    // ... index.js code
</script>

I don't want to make make inject to true, how can I solve this problem?

inlined script should be escaped

the inlined script including string "</script>" should be escaped.

quick fix is, at the end of processTag(),

tag.innerHTML = (tag.tagName === 'script') ? updatedSource.replace(/<\/script>/g, '<\\/script>') : updatedSource;

I'm not expert of Javascript/HTML, and not sure it's appropriate changes.

ParseError

I get the following error when I try to run the plugin

Error: Parse Error: <\?xml/,end:/\?>/,relevance:10},{begin:/<\?\w+/,end:/\?>/}]},{className:"tag",begin:"</?",end:"/?>",contains:[{className:"name",begin:/[^\/><\s]+/,relevance:0},n]}]}}}

My config:

 new HtmlWebpackPlugin({
    template: paths.client('landing.html'),
    inlineSource: '.(js|css)$',
    hash: false,
    filename: `landing.[${config.compiler_hash_type}].html`,
    chunks: ['landing'],
    injectSrc: true,
    inject: 'body',
    minify: {
      collapseWhitespace: true
    }
  }),
  new HtmlWebpackInlineSourcePlugin(),

Inline font assets

I have a custom index.html like this:

<!DOCTYPE html>
<html lang="en">
  <head>
     <style>
        @font-face {
          font-family: Inter;
          src: url("<%= ?????? %>") format("woff2");
        }
     </style>

I would like to get the font asset file that might look like inter.hash123.woff and place it in the inline style CSS.

How to inline .css from a <link> tag?

First of all, great plugin. Appreciate the work put into it.

I am trying to inline the .css source that comes from my <link> tag in the template file into the quoted.html file. Is this possible? If not, how do you inline CSS into the finalized file?

Inside plugins:
new HtmlWebpackPlugin({
inlineSource: '.(js|css)$',
filename: 'quoted.html',
template: 'src/quoted/quotedTemplate.html'
})
new HtmlWebpackInlineSourcePlugin()

Cannot use html-webpack-exclude-assets-plugin with this one

I was trying to use both (html-webpack-inline-source-plugin & html-webpack-exclude-assets-plugin) of these plugins together but the build resulted in an some errors:

ERROR in   TypeError: Cannot read property 'options' of undefined

  - index.js:19 Compilation.<anonymous>
    [MyProj]/[html-webpack-inline-source-plugin]/index.js:19:33

  - Tapable.js:206
    [MyProj]/[tapable]/lib/Tapable.js:206:14

  - index.js:30 Compilation.<anonymous>
    [MyProj]/[html-webpack-exclude-assets-plugin]/index.js:30:7

  - Tapable.js:208 Compilation.applyPluginsAsyncWaterfall
    [MyProj]/[tapable]/lib/Tapable.js:208:13

  - index.js:636
    [MyProj]/[html-webpack-plugin]/index.js:636:12

  - index.js:152
    [MyProj]/[html-webpack-plugin]/index.js:152:16

this is re-producible just by turning both of them on and running it vs. turning only one of them on at a time.

// gives no error
  new HtmlWebpackPlugin({
    title: title,
    template: 'index.html',
    excludeAssets: [ /some-file/ ],
    // inlineSource: '.(js|css)$',
  }),
  new HtmlWebpackExcludeAssetsPlugin(),
  // new HtmlWebpackInlineSourcePlugin(),
// gives errors
  new HtmlWebpackPlugin({
    title: title,
    template: 'index.html',
    excludeAssets: [ /some-file/ ],
    inlineSource: '.(js|css)$',
  }),
  new HtmlWebpackExcludeAssetsPlugin(),
  new HtmlWebpackInlineSourcePlugin(),

Versions:

    "html-webpack-exclude-assets-plugin": "^0.0.3",
    "html-webpack-inline-source-plugin": "^0.0.6",
    "html-webpack-plugin": "^2.26.0",
    "webpack": "2.2.0-rc.7",

Setting hash:true in HtmlWebpackPlugin breaks inlining

Description

I'm attempting to inline the source of a script while also importing external scripts with hashes (for cache breaking). However, setting hash: true in my HtmlWebpackPlugin options forces all the scripts to become external (no more inlining).

Config

module.exports = {
  entry: {
    internalScript: './pages/snippets/internalScript.js',
    externalScript: './externalScript.js',
  ...
  plugins: [
     new HtmlWebpackPlugin({
      template: 'pages/index.handlebars',
      inlineSource: 'internalScript.js\\S+$',
      inject: 'head',
      chunks: [
        'externalScript',
        'internalScript'
      ],
      hash: true
    }),
    new HtmlWebpackInlineSourcePlugin()
  ]
}

Environment

npm --version
npm ls webpack
npm ls html-webpack-pluginNode.js v6.3.0
darwin 16.6.0
npm ls webpack
npm ls html-webpack-plugin3.10.3
npm ls html-webpack-plugin
[email protected] ...
└── [email protected] 
[email protected] ...
├── [email protected] 
└─┬ [email protected]
  └── [email protected] 

Could I use template?

When inject is true, it works.

new HtmlWebpackPlugin({
    minify : false,
    filename,
    inlineSource : '.(js|css)$',
})

I want to use template to control the position of script.

new HtmlWebpackPlugin({
    minify : false,
    inject : false,
    filename,
    template,
    inlineSource : '.(js|css)$',
})

And the template like this,

<% for (key in htmlWebpackPlugin.files.chunks) { %>
<script src="<%= htmlWebpackPlugin.files.chunks[key].entry %>" type="text/javascript"></script>
<% } %>

And which attribute is the source ?

Inlining .svg files

Would you consider merging a pull request that adds the functionality of inlining .svg files;

Like;

<img src="static/media/icon.324fsdf.svg" style="..." class="..."/>

turns into;

<svg version="1.1"  style="..." class="...">
  <path ... >
</svg>

Or straight-up adding the html-webpack-inline-svg-plugin into this? Shouldnt we consider .svg files source files?

TypeError: Cannot read property 'source' of undefined

image

my config

I set filename as path.resolve(settings.output,v,v+'.html'), get error.
but set path.resolve(settings.output,v+'.html') correctly
'use strict'
let webpack = require('webpack')
let path = require('path')
let fs = require('fs')
let logger = require('log4js')
let log = logger.getLogger()
let CopyWebpackPlugin = require('copy-webpack-plugin');
let HtmlWebpackPlugin = require('html-webpack-plugin')
let HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
let config = {}
module.exports = {
  config: function (settings) {
    var me = this
    me.plugin(settings);
    me.output(settings)
    me.loaders()
    me.entry(settings)
    // log.info(JSON.stringify(config))
    // return
    return config
  },
  output: function (settings) {
    config.output = {
      path: settings.output,
      filename: "[name]"
    }
    if (settings.env == 'dev') {
      config.output.publicPath = "/www/build/"
    }
  },
  entry: function (settings) {
    config.entry = {}
    // entry
    let arr = settings.dir ? settings.dir.split(',') : fs.readdirSync(path.resolve(settings.projectPath, 'src'))
    arr.forEach(function (v, i) {
      let temp = path.resolve(settings.projectPath, 'src', v + '/')
      if (v !== 'script' && fs.lstatSync(temp).isDirectory()) {

        fs.readdirSync(temp).forEach(function (value, index) {
            if (path.extname(value) == '.js') {
              let key = v + '/' + value
              let val = ['./src/' + key]
              if (settings.env == 'dev') {
                val.push("webpack-dev-server/client?http://localhost:8080/", "webpack/hot/dev-server")
              }
              config.entry[key] = val
              // production
              // log.info(path.resolve(settings.output,v,v+'.html'))
              // return
              if (settings.env == 'prod') {
                config.plugins.push(new HtmlWebpackPlugin({
                  // inject:true,
                  template: './html/' + v + '.html',
                  // hash:false,
                  chunks:[key],
                  inlineSource: '.(js|css)$',
                  // filename:path.resolve(settings.output,'html',v+'.html')
                  filename:path.resolve(settings.output,v,v+'.html')
                }))
              }
              // add html plugin to js
              if (settings.env == 'dev') {
                config.plugins.push(new HtmlWebpackPlugin({
                  template: './html/' + v + '.html',
                }))
              }
            }

        })
      }
    })
  },
  loaders: function () {
    config.module = {}
    config.module.loaders = [
      {
        test: /\.scss$/,
        loaders: ["style", "css", "sass"]
      },
      {
        test: /\.html$/,
        loader: "raw-loader"
      }
    ]
  },
  plugin: function (settings) {
    // plugins
    config.plugins = [
      new CopyWebpackPlugin([{from: './src/script', to: settings.output + '/script/'}]),
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(settings.env)
      })
    ]
    if (settings.env == 'dev') {
      config.plugins.push(new webpack.HotModuleReplacementPlugin())
    }
    if (settings.env == 'prod') {
      config.plugins.push(
        new webpack.optimize.UglifyJsPlugin({
          compressor: {
            warnings: false,
          }
        }), new HtmlWebpackInlineSourcePlugin()
      )
    }
  }
}

Build falls after upgrading webpack to v4

The usage of the plugin is regular. I will provide more info if needed.

ERROR in   TypeError: callback is not a function
  
  - index.js:27 
    [Auth0-Config]/[html-webpack-inline-source-plugin]/index.js:27:7
  
  
  - new Promise
  
  
  - Hook.js:35 AsyncSeriesWaterfallHook.lazyCompileHook [as _promise]
    [Auth0-Config]/[tapable]/lib/Hook.js:35:21
  
  - index.js:679 
    [Auth0-Config]/[html-webpack-plugin]/index.js:679:45
  
  - index.js:170 
    [Auth0-Config]/[html-webpack-plugin]/index.js:170:16
  
  - util.js:16 tryCatcher
    [Auth0-Config]/[bluebird]/js/release/util.js:16:23
  
  - promise.js:512 Promise._settlePromiseFromHandler
    [Auth0-Config]/[bluebird]/js/release/promise.js:512:31
  
  - promise.js:569 Promise._settlePromise
    [Auth0-Config]/[bluebird]/js/release/promise.js:569:18
  
  - promise.js:614 Promise._settlePromise0
    [Auth0-Config]/[bluebird]/js/release/promise.js:614:10
  
  - promise.js:693 Promise._settlePromises
    [Auth0-Config]/[bluebird]/js/release/promise.js:693:18
  
  - async.js:133 Async._drainQueue
    [Auth0-Config]/[bluebird]/js/release/async.js:133:16
  
  - async.js:143 Async._drainQueues
    [Auth0-Config]/[bluebird]/js/release/async.js:143:10
  
  - async.js:17 Immediate.Async.drainQueues
    [Auth0-Config]/[bluebird]/js/release/async.js:17:14
  


ERROR in   TypeError: callback is not a function
  
  - index.js:27 
    [Auth0-Config]/[html-webpack-inline-source-plugin]/index.js:27:7
  
  
  - new Promise
  
  
  - index.js:679 
    [Auth0-Config]/[html-webpack-plugin]/index.js:679:45
  
  - index.js:170 
    [Auth0-Config]/[html-webpack-plugin]/index.js:170:16
  
  - util.js:16 tryCatcher
    [Auth0-Config]/[bluebird]/js/release/util.js:16:23
  
  - promise.js:512 Promise._settlePromiseFromHandler
    [Auth0-Config]/[bluebird]/js/release/promise.js:512:31
  
  - promise.js:569 Promise._settlePromise
    [Auth0-Config]/[bluebird]/js/release/promise.js:569:18
  
  - promise.js:614 Promise._settlePromise0
    [Auth0-Config]/[bluebird]/js/release/promise.js:614:10
  
  - promise.js:693 Promise._settlePromises
    [Auth0-Config]/[bluebird]/js/release/promise.js:693:18
  
  - async.js:133 Async._drainQueue
    [Auth0-Config]/[bluebird]/js/release/async.js:133:16
  
  - async.js:143 Async._drainQueues
    [Auth0-Config]/[bluebird]/js/release/async.js:143:10
  
  - async.js:17 Immediate.Async.drainQueues
    [Auth0-Config]/[bluebird]/js/release/async.js:17:14

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.