dustinjackson / html-webpack-inline-source-plugin Goto Github PK
View Code? Open in Web Editor NEWEmbed javascript and css source inline when using the webpack dev server or middleware
License: MIT License
Embed javascript and css source inline when using the webpack dev server or middleware
License: MIT License
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?
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
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
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
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
}>
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()
]
};
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
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);
}
}
});
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:
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?
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?
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?
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.
I am still getting main.js. Can you remove that?
It rebuilds the bundled .js file, but not the inlined HTML.
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),
If anyone would like to help maintain this plugin please send me a message
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.
My config has too many entrys.
It takes the same time as webpack uglify which build 7205ms.
So,is possiable to take less time to build?(like https://github.com/gdborton/webpack-parallel-uglify-plugin)
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.
What do you think about adding a new feature, which allow you to add custom attributes to inline <script> tags?
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);
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 containing
declare module 'html-webpack-inline-source-plugin';ts(7016)](url)
What do I need to do to solve this problem?
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?
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! :(
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! :)
Hi,
I was wondering whether this plugin accounts for code-splitting? I'm using react-loadable, but would love to inline the main bundle to speed up the first request. Please let me know. Thank you!
Kind regards,
Harry
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?
It wasn't working with html-webpack-plugin 2.22.0 but worked perfectly with 2.29.0 & 2.30.1.
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
Plugin processing preload node
Does the plugin need to skip the preload , prefetch node?
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.
The size of my html file increased to 30.4kb
And I found that my css file was inlined twice.
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()
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
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'
'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.
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
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:
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`
})
]
};
//# sourceMappingURL=/foo/bar/https:/example.com/main.js.map
//# 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.
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 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(),
]
}
webpack run causes the error.
webpack version is 2.3.2.
Error message:
ERROR in TypeError: Cannot read property 'source' of undefined
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 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?
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.
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(),
Using index.js
from https://github.com/DustinJackson/html-webpack-inline-source-plugin/pull/55/files works just fine.
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.
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()
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",
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).
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()
]
}
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]
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 ?
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?
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()
)
}
}
}
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.