Giter VIP home page Giter VIP logo

webpack-pwa-manifest's Introduction

webpack-pwa-manifest

Looking for people willing to help! More info

webpack-pwa-manifest is a webpack plugin that generates a 'manifest.json' for your Progressive Web Application, with auto icon resizing and fingerprinting support.

If you are using inject on your configuration, ensure that HtmlWebpackPlugin appears before WebpackPwaManifest in the plugins array!

features

✔ Auto icon resizing

✔ Icon fingerprinting

✔ Manifest fingerprinting

✔ Auto manifest injection on HTML

✔ Hot Reload support

✔ ES6+ ready

install

npm install --save-dev webpack-pwa-manifest

usage

In your webpack.config.js:

// ES6+
import WebpackPwaManifest from 'webpack-pwa-manifest'

// ES5
var WebpackPwaManifest = require('webpack-pwa-manifest')

...

plugins: [
  new WebpackPwaManifest({
    name: 'My Progressive Web App',
    short_name: 'MyPWA',
    description: 'My awesome Progressive Web App!',
    background_color: '#ffffff',
    crossorigin: 'use-credentials', //can be null, use-credentials or anonymous
    icons: [
      {
        src: path.resolve('src/assets/icon.png'),
        sizes: [96, 128, 192, 256, 384, 512] // multiple sizes
      },
      {
        src: path.resolve('src/assets/large-icon.png'),
        size: '1024x1024' // you can also use the specifications pattern
      },
      {
        src: path.resolve('src/assets/maskable-icon.png'),
        size: '1024x1024',
        purpose: 'maskable'
      }
    ]
  })
]

output

manifest.<fingerprint>.json

{
  "name": "My Progressive Web App",
  "orientation": "portrait",
  "display": "standalone",
  "start_url": ".",
  "short_name": "MyPWA",
  "description": "My awesome Progressive Web App!",
  "background_color": "#ffffff",
  "icons": [
    {
      "src": "icon_1024x1024.<fingerprint>.png",
      "sizes": "1024x1024",
      "type": "image/png",
      "purpose": "maskable"
    },
    {
      "src": "icon_1024x1024.<fingerprint>.png",
      "sizes": "1024x1024",
      "type": "image/png"
    },
    {
      "src": "icon_512x512.<fingerprint>.png",
      "sizes": "512x512",
      "type": "image/png"
    },
    {
      "src": "icon_384x384.<fingerprint>.png",
      "sizes": "384x384",
      "type": "image/png"
    },
    {
      "src": "icon_256x256.<fingerprint>.png",
      "sizes": "256x256",
      "type": "image/png"
    },
    {
      "src": "icon_192x192.<fingerprint>.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "icon_128x128.<fingerprint>.png",
      "sizes": "128x128",
      "type": "image/png"
    },
    {
      "src": "icon_96x96.<fingerprint>.png",
      "sizes": "96x96",
      "type": "image/png"
    }
  ]
}

API

WebpackPwaManifest([options])

options

Type: object

You can follow the Web App Manifest specification.

The difference here is that, when defining icons, you can specify one icon with multiple sizes, using an array of integers, just as the example above.

You can also change the output's filename with the filename property.

Presets of options:

{
  filename: "manifest.json",
  name: "App",
  orientation: "portrait",
  display: "standalone",
  start_url: ".",
  crossorigin: null,
  inject: true,
  fingerprints: true,
  ios: false,
  publicPath: null,
  includeDirectory: true
}

By default, HTML injection and fingerprint generation are on. With inject: false and fingerprints: false, respectively, you can turn them off.

If inject: true and 'theme-color' property is not defined, it wil try to use theme_color as default. Otherwise, no theme-color meta tag will be injected.

With includeDirectory: true, we will use filename's directory to export the manifest file.

With orientation: 'omit', the orientation key will be omitted from the generated manifest file.

When inject: true and ios: true, specific Apple meta tags will be injected to the HTML code when possible, as requested at issue #13. You can see Apple's Configuring Web Application for more information. Instead of using a boolean value, you can also use an object to specify certain link or meta tag, for instance:

  ...
  ios: {
    'apple-mobile-web-app-title': 'AppTitle',
    'apple-mobile-web-app-status-bar-style': 'black'
  }

If publicPath option is not given, this plugin fallbacks to Webpack's public path definition.

When defining an icon object, you can also specify its output directory using a property called destination. Using ios: true in an icon object makes it eligible to the apple-touch-icon meta tag injection. Using ios: 'startup' in an icon object makes it eligible to the apple-touch-startup-image meta tag injection.

  ...
  icons: [
    {
      src: path.resolve('src/assets/icons/ios-icon.png'),
      sizes: [120, 152, 167, 180, 1024],
      destination: path.join('icons', 'ios'),
      ios: true
    },
    {
      src: path.resolve('src/assets/icons/ios-icon.png'),
      size: 1024,
      destination: path.join('icons', 'ios'),
      ios: 'startup'
    },
    {
      src: path.resolve('src/assets/icons/android-icon.png'),
      sizes: [36, 48, 72, 96, 144, 192, 512],
      destination: path.join('icons', 'android')
    }
  ]
}

If you specify a valid crossorigin property it will be added to the <link rel="manifest"> in the HTML document. This property determines if the request for the manifest includes CORS headers and is required if the manifest is located on a different domain or requires authentication.

webpack-pwa-manifest's People

Contributors

arthurbergmz avatar arthurconexia avatar chris3773 avatar colt45s avatar deleonio avatar dobladov avatar doug-wade avatar filipchalupa avatar istoramandiri avatar jeandecampredon avatar kenrick95 avatar kevinchappell avatar lwakefield avatar remcoman avatar satazor avatar sebastiangoeb avatar stanzilla avatar wilsonpage 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  avatar  avatar  avatar  avatar

webpack-pwa-manifest's Issues

Add auto <meta name="theme-color"> injection on HTML.

Lighthouse is showing me the following error:

Address bar does not match brand colors
Failures: No `<meta name="theme-color">` tag found.

More info about this here.

My config:

new WebpackPwaManifest({
   name: 'My Progressive Web App',
   short_name: 'MyPWA',
   description: 'My awesome Progressive Web App!',
   start_url: '/',
   background_color: '#00b2ff',
   theme_color: '#00b2ff',
   'theme-color': '#00b2ff',
   icons: [{
      src: path.resolve(__dirname, '../../assets/js.png'),
      sizes: [96, 128, 192, 256, 384, 512],
      destination: 'icons'
   }]
})

Custom properties in manifest like gcm_sender_id

Hi, thank you for the plugin!

I was wondering if it's possible to set a custom property in manifest.json? What I'm trying to achieve is to have this field:

{
  "gcm_sender_id": "547903344792"
}

According to web push book it's required to setup Google Cloud Messaging.

Webpack 4 support

Webpack 4 is currently in beta (should be released in Feb 2018) and introduce a new plugin system (called tap).

Output name interpolation

Webpack along with many loaders and plugins allow specifying output filenames in interpolated formats such as [name].[ext] and[name].[hash].[ext], which are also used for configuration between development and production to toggle what this plugin has "fingerprint" option for.

Currently the naming of output icons is quite hardcoded:

const sizeFormat = `${size}x${size}`
const filename = fingerprint ? `icon_${sizeFormat}.${generateFingerprint(buffer)}.${mime.extension(type)}` : `icon_${sizeFormat}.${mime.extension(type)}`
const output = icon.destination ? joinURI(icon.destination, filename) : filename

It would be great to have support for customizing the filename format using Webpack "standardized" interpolated names, allowing the default format to be something like icon_[size]x[size].[ext] or icon_[size]x[size].[hash].[ext]. Note the custom [size] parameter. Specifying a custom name format would probably have to override the default and also "fingerprint" option.

A similar but separate interpolated format could probably exist for naming the manifest.json file, although it would not be as necessary as being able to name the icons.

loader-utils#interpolateName() is what seems to be able to do the necessary translations.

webpack-dev-server crashes

I'm getting this weird error while running with webpack-dev-server

webpack: Compiling...
 95% emitting(node:641) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: icon.sizes.pop is not a function
(node:641) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Here is my webpack.cong.js:

new WebpackPwaManifest({
      "name": METADATA.title,
      "short_name": METADATA.title,
      "description": METADATA.description,
      "background_color": METADATA.backgroundColor,
      "start_url": "./?utm_source=web_app_manifest",
      "dir": "rtl",
      "lang": "en-US",
      "icons": [
        {
          "src": path.join(process.cwd(), "src/assets/icons/icon.png"),
          "sizes": [120, 152, 167, 180, 1024],
          "destination": path.join("icons", "ios")
        },
        {
          "src": path.join(process.cwd(), "src/assets/icons/icon.png"),
          "sizes": [32, 36, 48, 72, 96, 144, 192, 512],
          "destination": path.join("icons", "android")
        }
      ]
    }),

Thanks

Build Error: Cannot read property 'Symbol(Symbol.iterator)' of null

Hi, this is working for me with version 2.7, but breaks when using version 3:

TypeError: Cannot read property 'Symbol(Symbol.iterator)' of null
    at Compiler.<anonymous> (/Users/chris/code/xxx/node_modules/webpack-pwa-manifest/dist/WebpackPwaManifest.js:71:51)
    at next (/Users/chris/code/xxx/node_modules/tapable/lib/Tapable.js:140:14)
    at /Users/chris/code/xxx/node_modules/optimize-css-assets-webpack-plugin/index.js:97:27
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:169:7)

tapAsync issue with webpack 4

Hi I'm having this issue when I use webpack or webpack-dev-server

/asdf/node_modules/webpack-dev-server/bin/webpack-dev-server.js:405
    throw e;
    ^

TypeError: Cannot read property 'tapAsync' of undefined
    at /asdf/node_modules/webpack-pwa-manifest/dist/generators/tapable.js:11:61
    at SyncHook.eval [as call] (eval at create (/asdf/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:17:12), <anonymous>:13:1)
    at SyncHook.lazyCompileHook [as _call] (/asdf/node_modules/webpack/node_modules/tapable/lib/Hook.js:35:21)
    at Compiler.newCompilation (/asdf/node_modules/webpack/lib/Compiler.js:418:26)
    at hooks.beforeCompile.callAsync.err (/asdf/node_modules/webpack/lib/Compiler.js:457:29)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/asdf/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:24:12), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook [as _callAsync] (/asdf/node_modules/webpack/node_modules/tapable/lib/Hook.js:35:21)
    at Compiler.compile (/asdf/node_modules/webpack/lib/Compiler.js:452:28)
    at compiler.hooks.watchRun.callAsync.err (/asdf/node_modules/webpack/lib/Watching.js:77:18)
    at _err0 (eval at create (/asdf/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:24:12), <anonymous>:11:1)
    at invalid (/asdf/node_modules/webpack-dev-middleware/lib/context.js:76:7)
    at context.compiler.plugin (/asdf/node_modules/webpack-dev-middleware/lib/context.js:116:5)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/asdf/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:24:12), <anonymous>:7:1)
    at AsyncSeriesHook.lazyCompileHook [as _callAsync] (/asdf/node_modules/webpack/node_modules/tapable/lib/Hook.js:35:21)
    at Watching._go (/asdf/node_modules/webpack/lib/Watching.js:40:32)
    at Watching.compiler.readRecords.err (/asdf/node_modules/webpack/lib/Watching.js:32:9)
error An unexpected error occurred: "Command failed.
Exit code: 1

not support protocol less url

publicPath //example.com/path/ generate

<link rel="manifest" href="/example.com/path/manifest.json" />  

publicPath http://example.com/path/ generate

<link rel="manifest" href="http://example.com/path/manifest.json" />  

How to use in template

I'm still missing how do I add this to my template. HtmlWebpackPlugin automatically handles chunks, but this is not a chunk, I guess.

Got manifest.[hash].json but dont know how to inject it on custom template

Hi! First of all, I want to thank you guys for this awesome plugin.

Now, what is happening to me is this: I need to add a web app manifest.json file to my web app to make it Progressive. Im indeed getting the file generated by the plugin, but since Im not using HtmlWebpackPlugin, Im not being able to include/inject it.

For my project, I rely on assets-webpack-plugin to get a webpack-assets.json with all the mappings of entry name vs hashed file, and in my custom template (.pug file, ex .jade) I include a reference to them. That's how I get all my js/css outputs working.

So my question is this: is there a way to add the manifest link tag to my custom template?

In other words, after each webpack build I end up with a manifest.[hash].json file that I cannot reference by name in my html/pug since the hash always changes with each build.

Manifest: property 'sizes' ignored

Manifest: property 'sizes' ignored, type string expected.

Looks like Chrome doesn't like the sizes array. Maybe something to investigate according to the official documentation.

Generating favicon.ico

It would be cool if this plugin could generate a .ico file as one of the output icons.

UnhandledPromiseRejectionWarning

Unfortunately, I'm getting a new error while Webpack is is compiling:

webpack: Compiling...
 95% emitting(node:26089) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: icon.sizes.pop is not a function

Small problem when `publicPath` is empty

I'm having a small problem when trying to use this plugin with webpack's publicPath (from output config) as ('' - an empty string).

Problem

The asset generated is:

(note the first slash)

<link rel="manifest" href="/manifest.eb687d814aa4397c0e0ed4e8af308e43.json" />

Expected:

(without the first slash)

<link rel="manifest" href="manifest.eb687d814aa4397c0e0ed4e8af308e43.json" />

Why I need this:

My use case is that I don't know - at build time - where from my assets will be served. I have an nginx that serves the html and will handle the paths to all assets (so, it will handle any assets served from any given path).

Possible Cause:

The code that is causing this is here:

return normalizeURI(arr.join('/'))

This is caused because you're doing a simple array concatenation, so, it doesn't handle empty values.

['', 'manifest.json']; // '/manifest.json' (my problem)
[1, 2, 3].join('/'); // 1/2/3
[1, '', 2, '', 3]; // 1//2//3

Possible Fix:

If you don't see any problems, I think we can use nodejs's path.join:

path.join('', 'manifest.json'); // manifest.json
path.join('1', '2', '3'); // 1/2/3
path.join('1', '', '2', '', '3'); // 1/2/3

I also think that it's more reliable to use path module for those kind of file paths manipulation instead of doing this manually.

What do you think?

If you think it's good, I can write a PR for that!

Thank you. Nice project btw! It solved our problems!

iOS Web Application Configuration

iOS uses special <meta> tags for Web Application Configuration as opposed to the Web App Manifest. The functionality of both overlaps a lot so I think it makes sense if this plugin could optionally also inject iOS-specific Web App Configuration <meta> tags as the information is already being put into manifest.json. Having a separate plugin for just that sounds excessive. It would make this plugin much better suited for production use where iOS devices also need to be supported.

A new plugin option, e.g. ios could be added for this. A false value (possibly by default to keep existing behavior) would disable the injection of these <meta> tags. A true value would enable this injection. An object might also be sensible to support as the value to specify iOS only configuration (launch screen image, whether to inject icons normally or precomposed, etc).

Unable to include SVG icons

If there's a SVG icon inside icons, this package fails with the following error:

It was not possible to read 'src/icons/some.svg'.

This happens because we are using jimp to resize the images but it doesn't support SVGs. And it shouldn't because SVGs are scalable by nature, thus they don't need to be resampled. My suggestion is to detect SVGs via the type (and fallback to extension) and skip jimp if the detection identified a SVG.

Do you agree with this? If so, I will make a PR to implement this strategy.

How to define publicPath?

The injected HTML file path path doesn't seem to respect the publicPath option defined in my webpack config.

My Webpack config:

output: {
  ...
  publicPath: '/static/',
  ...
},
...

Expected:

<link rel="manifest" href="/static/manifest.593b44ef40ae0879f60c80e4156d2958.json">

Actual:

<link rel="manifest" href="manifest.593b44ef40ae0879f60c80e4156d2958.json">

callback is not a function (webpack v4)

I've upgraded to the latest version of [email protected] and [email protected] and am seeing this error when running my current build

Child html-webpack-plugin for "index.html":
     1 asset
    Entrypoint undefined = index.html
       [3] ../node_modules/html-webpack-plugin/lib/loader.js!./index.html 843 bytes {0} [built]
        + 3 hidden modules
/Users/owenbuckley/Workspace/pvdgeeks.org/website-frontend/node_modules/webpack-pwa-manifest/dist/index.js:72
            callback(null, htmlPluginData);
            ^

TypeError: callback is not a function
    at /Users/owenbuckley/Workspace/pvdgeeks.org/website-frontend/node_modules/webpack-pwa-manifest/dist/index.js:72:13
    at /Users/owenbuckley/Workspace/pvdgeeks.org/website-frontend/node_modules/webpack-pwa-manifest/dist/injector/index.js:96:9
    at manifest (/Users/owenbuckley/Workspace/pvdgeeks.org/website-frontend/node_modules/webpack-pwa-manifest/dist/injector/index.js:76:3)
    at /Users/owenbuckley/Workspace/pvdgeeks.org/website-frontend/node_modules/webpack-pwa-manifest/dist/injector/index.js:92:7
    at processNext (/Users/owenbuckley/Workspace/pvdgeeks.org/website-frontend/node_modules/webpack-pwa-manifest/dist/icons/index.js:107:14)
    at Jimp.<anonymous> (/Users/owenbuckley/Workspace/pvdgeeks.org/website-frontend/node_modules/webpack-pwa-manifest/dist/icons/index.js:134:16)
    at /Users/owenbuckley/Workspace/pvdgeeks.org/website-frontend/node_modules/jimp/index.js:2255:27
    at /Users/owenbuckley/Workspace/pvdgeeks.org/website-frontend/node_modules/stream-to/index.js:39:7
    at exports.PNG.onEnd (/Users/owenbuckley/Workspace/pvdgeeks.org/website-frontend/node_modules/stream-to/index.js:18:5)
    at Object.onceWrapper (events.js:313:30)
    at emitNone (events.js:106:13)
    at exports.PNG.emit (events.js:208:7)
    at emitNone (events.js:106:13)
    at module.exports.emit (events.js:208:7)
    at module.exports.<anonymous> (/Users/owenbuckley/Workspace/pvdgeeks.org/website-frontend/node_modules/pngjs/lib/packer-async.js:41:10)
    at emitNone (events.js:111:20)
    at Deflate.emit (events.js:208:7)
    at endReadableNT (_stream_readable.js:1055:12)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Likely this is related to some breaking change?
https://medium.com/webpack/webpack-4-migration-guide-for-plugins-loaders-20a79b927202

You can see my PR here in my project where if you resnable WebpackPwaManifest in webpack.config.prod.js and ran yarn build, you can reproduce the error.

Is there any plan for an upgrade? Any pointers for someone to contribute it? Thanks for the great work on this plugin! 🙏 ✌️

Custom publicPath option

As I understand, this plugin right now only reads from webpack output publicPath.

One use case for this is that site assets are served at CDN but would like to serve manifest.json under own site (i.e. non-CDN). At current configuration, where manifest.json is served at CDN (which has different origin from own site's origin), Chrome will throw this warning: Manifest: property 'start_url' ignored, should be same origin as document. at console.

I realized that there is no way to specify custom publicPath yet for this plugin and would like to have that option.

Thanks

Choosing which icons are linked in the webmanifest

It would be good if the configuration allowed the user to specify if a group of icons should be included in the manifest file.

Example:

"icons": [
  {
    "src": "src/images/favicon.png",
    "sizes": [48, 144, 512],
    "manifest": true
  },
  {
    "src": "src/images/favicon.png",
    "sizes": [180],
    "ios": true,
    "manifest": false
  } 
]

ERROR in TypeError: supportedMimeTypes.includes is not a function

Hi,

This is probably just something I am doing wrong or the version of webpack I'm using but I thought I would report this just in case:

When adding icons to the config and building webpack the icons aren't created due to this error:

ERROR in   TypeError: supportedMimeTypes.includes is not a function
  - index.js:117 process
    [mk2]/[webpack-pwa-manifest]/dist/icons/index.js:114:29

I am using

"webpack": "^3.10.0",
"webpack-pwa-manifest": "^3.6.2"

My config object is

new WebpackPwaManifest({
     name: 'Name',
     short_name: 'CoolName',
     description: 'MySite',
     background_color: '#FFFFFF',
     inject: true,
     ios: true,
     icons: [
         {
             src: './src/images/icon.png',
             sizes: [96, 128, 192],
             ios: true
         }
     ]
 })

Changing line 114 in webpack-pwa-manifest]/dist/icons/index.js from

if (!supportedMimeTypes.includes(mimeType)) {

to

if (supportedMimeTypes.indexOf(mimeType) === -1) {

fixes the issue and icons generate fine.

Use webpack output path for icons src

I got a trouble using manifest, because output manifest contains absoulute path, not relative to my output path.

  output: {
     publicPath: '/assets/'
  },
  new WebpackPwaManifest({
      background_color: '#ffffff',
      theme_color: '#2196f3',
      start_url: '/',
      icons: [
        {
          src: path.resolve(__dirname, '..', '..', '..', 'public', 'assets', 'icon.png'),
          sizes: [36, 48, 57, 72, 96, 114, 144, 192] // multiple sizes
        }
      ]
    })

manifest.json:

{
      "src": "assets/icon_192x192.7d461de01ff05a5ceb29aaca7ef5695f.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "assets/icon_144x144.8f737a65911f044a30e8ec64a14c6668.png",
      "sizes": "144x144",
      "type": "image/png"
    },
    {
      "src": "assets/icon_114x114.5ed529289e704528d188cf8798650827.png",
      "sizes": "114x114",
      "type": "image/png"
},

add Travis CI integration for continuous-integration testing

it'd be great to set this project to use the Travis CI (via the free GitHub integration) service, which is free (for OSS projects).

the tests could then be run on pull requests (opened/modified), with reported test successes and failures (via the built-in hooks in the GitHub integration).

let me know if you want help with this. (related: for issue #63, I did some troubleshooting with the tests, but I'm still stuck on why the test files cannot be found on my system.)

Emit file

Does this plugin emit the generated manifest.json? This way I could read it from my stats.json and include it in the HTML source (we're using React instead of HtmlWebpackPlugin).

Thanks for the great work!

is it necessary to preserve IOS icon in the manifest.json?

This is a question.

I try to use different icon for ios and android like below:

{
  ios: true,
  icons: [
    {
      src: path.resolve('public/android-icon.png'),
      sizes: [144, 196, 256, 512],
      destination: 'android'
    },
    {
      src: path.resolve('public/ios-icon.png'),
      sizes: [144, 196, 256, 512],
      ios: true,
      destination: 'ios'
    }
  ]
}

The plugin works well, insert app-touch-icon into html, while still preserve related icon in the manifest.json, I wonder that, if this will cause browser pick the wrong icon? or, use different icon is just bad idea?

Recursive output folder creation with 3.3.4 release

Hello,

With following version of packages:
"webpack": "~3.10.0",
"webpack-hot-middleware": "~2.21.0",
"webpack-pwa-manifest": "~3.3.4"

Each time the HMR rebuild sources, a new output folder with a manifest file is created inside the normal output folder, ending up after few rebuild with something like that:

/dist/[compiled sources]
/dist/manifest.json
/dist/dist/manifest.json
/dist/dist/manifest.json
/dist/dist/dist/manifest.json
/dist/dist/dist/dist/manifest.json
/dist/dist/dist/dist/dist/manifest.json
...

Everything was fine with "webpack-pwa-manifest": "~3.3.2"

Webpack has the conf output.publicPath set to '/dist/' and output.path set to path.join(__dirname, './ClientApp/dist')

manifest.json not injected

Hi,

my manifest.json is not injected in my html template

This is my plugins object:

const plugins = [
  new CopyPlugin([{ from: "./public" }]),
  new ExtractPlugin({
    filename: isProd ? "css/[chunkhash:7].min.css" : "css/[name].css",
    allChunks: true
  }),
  new HtmlPlugin({
    excludeChunks: ["polyfill"],
    inject: true,
    template: "./src/index.html",
    minify: { removeComments: isProd }
  }),
  new ManifestPlugin({
    filename: "manifest.json",
    name: "App",
    short_name: "App",
    description: "Description",
    fingerprints: false,
    orientation: "landscape"
  })
];

Is there a way to inject links to generated images?

Hey!
My problem is that I have many images of different sizes in my dist folder, but they are not injected into index.html. The images are recognized by the browser (I can see the icons in devtools) devtools -> application -> manifest, but favicon on browser tab is empty. Is it a bug or a feature or am I missing something?

1

Latest version (3.1.2) breaks the injected manifest URL in windows 10

PWA Configuration

new WebpackPwaManifest({
            name: packageConfig.name,
            short_name: 'Angular PWA',
            description: packageConfig.description,
            background_color: '#ffffff',
            theme_color: '#607d8b',
            inject: true,
            icons: [{
                src: path.resolve('src/assets/images/logo.png'),
                sizes: [96, 128, 192, 256, 384, 512],
                destination: path.join('assets', 'icons')
            },
            {
                src: path.resolve('src/assets/images/logo.png'),
                size: '1024x1024',
                destination: path.join('assets', 'icons')
            }
            ]
        })

Please see the difference,

html-webpack-plugin: 2.29.0
webpack: 3.3.0
webpack-pwa-manifest: 3.1.1

<link rel="manifest" href="\manifest.ef1097bcbf4ac5ce67f564d4256f7a35.json" /> its working fine

html-webpack-plugin: 2.29.0
webpack: 3.3.0
webpack-pwa-manifest: 3.1.2

<link rel="manifest" href="//manifest.d1684d7a301d4e6cc8cc450a1300a3ee.json" /> not working

Usage of webpack public path inconsistent

Related to #5

It seems I might have jumped too early. There is an issue with the option useWebpackPublicPath and its handling in the HtmlWebpackPlugin. First, I'm of the opinion that this option is irrelevant (the manifest.json should always be generated in the output path). Nevertheless, I'd like to go through the inconsistency of its usage right now. So, with following webpack options:

  • path: dist/
  • publicPath: /assets/

as ./dist and with the (default) value of false, it will:

  • generate the manifest.json in the output path: ./dist/manifest.[hash].json
  • inject the link tag <link rel="manifest" href="manifest.[hash].json" />

so, the file is in the proper place, but the url is wrong (it should contain the publicPath from webpack). when I switch it to true (use webpack public path):

  • generates the manifest.json in this path: ./dist/assets/manifest.[hash].json
  • inject the link tag <link rel="manifest" href="/assets/manifest.[hash].json" />

so now the URL is right, but the file isn't in the proper place, therefore the server will return 404.

My feeling is that, somewhere in the codebase, both options are being misused. Nevertheless, I'd remove the useWebpackPublicPath option altogether and just use the right webpack variables.

What do you think?

publicPath output files

Hey! First of all, thanks for your work!

I found something that could be a bit better. When using the publicPath option, the manifest file won't be generated in the specified path.

The manifest is always being generated at the root of the output path defined in the webpack config.

To fix this issue we would pass, as arguments, both the publicPath and the webpack output path to some functions that need it, instead of just "ignoring" the publicPath if it's not defined like we are doing here:

buildResources(_this, _this.options.publicPath || compilation.options.output.publicPath, () => {

We would replace this to something like:

buildResources(_this, _this.options.publicPath, compilation.options.output.publicPath, () => {

And with this we can make some logic around the publicPath option.

Right now, without any changes, the output of the manifest is only its name and its fingerprint. In this case it will always be generated in the webpack output path:

const output = options.fingerprints ? `${filename.name}.${generateFingerprint(json)}${filename.ext}` : `${filename.name}${filename.ext}`
callback(null, {
output,
file: joinURI(publicPath, output),

The idea would be to add the publicPath if it's provided by the user:

const outputSource = joinURI(publicPath || outputPath, output);
callback(null, {
    output: publicPath ? outputSource : output,
    file: outputSource,
...

---  ---

We also should address the icons. The icons destination property always starts at the same folder level as the manifest file right?

Having this in mind we can do the same thing as above. Instead of:

const output = icon.destination ? joinURI(icon.destination, filename) : filename
const outputSource = joinURI(publicPath, output)
icons.push({
src: outputSource,
sizes: sizeFormat,
type
})
assets.push({
output,
source: buffer,
size: buffer.length,

We could:

 const output = icon.destination ? joinURI(icon.destination, filename) : filename;
 const outputSource = (publicPath || outputPath, output); 
 icons.push({ 
   src: output,
   sizes: sizeFormat,
   type 
 }) 
 assets.push({ 
   output: publicPath ? outputSource : output,
   source: buffer, 
   size: buffer.length, 

---  ---

So... With this changes this is what would happen:

Case 1.
We define a publicPath: publicPath: 'my/path'.
We define an icon (192x192) with a pre-defined destination:

{ ...,
  destination: 'favicons'
}

We also define an icon (512x512) without a destination.

We would get an output like:

publicDir

└─── my
│         │
│         └─── path
│         │         │  
│         │         │  manifest.json
│         │         │  icon_512x512.png
│         │         └─── favicons
│         │         │          │  
│         │         │          │  icon_192x192.png

 
Case 2.
We don't define a publicPath and expect the plugin to use the already defined output config of webpack.

We define an icon (192x192) with a pre-defined destination:

{ ...,
  destination: 'favicons'
}

We also define an icon (512x512) without a destination.

We would get an output like:

publicDir

│manifest.json
│icon_512x512.png
└─── favicons
│         │  icon_192x192.png

---  ---

What do you think of this? Am I missing something?
If you think this might be a solution I would try to help and make a MR.

Thanks once again!

filename:'assets/manifest.json' will output 'assets\manifest.json' in webpack build output

Platform: windows 10 x64

I want generate manifest.json to assets directory, the plugin will output assets\manifest.json in webpack build output.
When i use workbox-webpack-plugin, it generate an error url in the precache-manifest.js file.
eg. "url": "/assets\\manifest.json"

Here is an example https://github.com/pfdgithub/workbox-webpack-plugin-demo/tree/webpack-pwa-manifest

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WorkboxPlugin = require('workbox-webpack-plugin');
const WebpackPwaManifest = require('webpack-pwa-manifest');

const assetsDir = 'assets';
const dist = path.resolve(__dirname, 'dist');

module.exports = {
  mode: 'development',
  entry: {
    index: './src/index.js'
  },
  output: {
    path: dist,
    publicPath: '/',
    filename: `${assetsDir}/[name].[chunkhash].js`
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html'
    }),
    new WebpackPwaManifest({
      includeDirectory: true,
      filename: `${assetsDir}/app-manifest.[hash].json`,
      icons: [{
        ios: true,
        sizes: [512],
        destination: assetsDir,
        src: './src/logo.png'
      }]
    }),
    new WorkboxPlugin.GenerateSW({
      swDest: 'service-worker.js'
    })
  ]
};

webpack output

Hash: 0ecad9f2cab750e7a3cc
Version: webpack 4.8.3
Time: 596ms
Built at: 2018-05-24 15:35:22
                                                    Asset       Size  Chunks             Chunk Names
                     assets/index.11e98c3468ca0dfc5163.js   3.13 KiB   index  [emitted]  index
                                               index.html  299 bytes          [emitted]
assets\app-manifest.36e24165d2402fe5e7ec9f697b21bf06.json  274 bytes          [emitted]
 assets/icon_512x512.b3439eb3160219d7c47744dc2872a86c.png   79.7 KiB          [emitted]
    precache-manifest.4cd74c7aeef71518564cbddcd702e275.js  337 bytes          [emitted]
                                        service-worker.js  908 bytes          [emitted]
Entrypoint index = assets/index.11e98c3468ca0dfc5163.js
[./src/index.js] 309 bytes {index} [built]
Child html-webpack-plugin for "index.html":
     1 asset
    Entrypoint undefined = index.html
    [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 509 bytes {0} [built]
    [./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 519 bytes {0} [built]
        + 2 hidden modules

precache-manifest.js

self.__precacheManifest = [
  {
    "revision": "042c69952b95a2f23315fcfb5cdb4643",
    "url": "/index.html"
  },
  {
    "url": "/assets\\app-manifest.36e24165d2402fe5e7ec9f697b21bf06.json"
  },
  {
    "url": "/assets/index.11e98c3468ca0dfc5163.js"
  },
  {
    "url": "/assets/icon_512x512.b3439eb3160219d7c47744dc2872a86c.png"
  }
];

Icon filename configuration

At the moment icon files are always named icon_[size].[fingerprint].[ext], but there are certain icons that are expected to have the same filename (e.g. /favicon.ico, apple-touch-icon.png).

It would be good if the plugin allowed more freedom in defining filename patterns at the icon config level. It would also be good if, by specifying the filename pattern, we could include the file hash.

This is an example of what the configuration could look like for the icons object:

"icons": [
  {
    "src": "src/images/favicon.png",
    "sizes": [16, 32],
    "filename": "favicon-[size].[hash].[ext]"
  },
  {
    "src": "src/images/favicon.png",
    "sizes": [180],
    "ios": true,
    "filename": "apple-touch-icon.[ext]"
  } 
]

Please let me know what do you think about these suggestions. I'd be also interested in helping you coding these features.

Thanks

Cache resized icons for faster builds

It would be great if the icons could be cached somewhere after resizing (maybe based on the last modified timestamp for the best performance) to get faster builds. Right now webpack-pwa-manifest adds ~8s to every build for me, which is a 25% increase.

I believe this is going to get more relevant when you implement #44 since the potential number of output files is going to grow by a fair margin in some configurations.

A good candidate for a cache path would be .cache/pwa-manifest I think, although ideally that would ideally be configurable as well.

And thank you for making such a useful piece of software of course :)

tests fail on macOS on `master`

first off, awesome project. thanks for creating this! 👍

when cloning master, the tests fail for me on macOS 10.13.2 (tested with Node.js version v8.91, v8.9.4, and v9.11.1.)

screenshot of tests in terminal

% npm test                                                                                                     /opt/webpack-pwa-manifest (master)

> [email protected] test /opt/webpack-pwa-manifest
> npm run build && node tests/index.js


> [email protected] build /opt/webpack-pwa-manifest
> babel src --out-dir dist

src/errors/IconError.js -> dist/errors/IconError.js
src/errors/PresetError.js -> dist/errors/PresetError.js
src/generators/legacy.js -> dist/generators/legacy.js
src/generators/tapable.js -> dist/generators/tapable.js
src/helpers/except.js -> dist/helpers/except.js
src/helpers/fingerprint.js -> dist/helpers/fingerprint.js
src/helpers/uri.js -> dist/helpers/uri.js
src/icons/index.js -> dist/icons/index.js
src/index.js -> dist/index.js
src/injector/index.js -> dist/injector/index.js
src/validators/colors.js -> dist/validators/colors.js
src/validators/presets.js -> dist/validators/presets.js
src/validators/versioning.js -> dist/validators/versioning.js
Running tests...
"basic": building...
"basic": testing...
Expected 5 file(s).
Found 0 file(s).
Test "basic" failed.

any ideas as to what is causing this on my machine?

[Discussion] Extend icon support

If you plan to release a new version for webpack 4, it's time for breaking change
Related to #39 I thought about remove ios property (in icons) and introduce a new type property, which could be:

  • favicon: inject <link rel=icon type=image/png sizes=##x## in index.html
  • safari : inject <link rel=apple-touch-icon in index.html (current ios: true)
  • edge: set icons in browserconfig.xml
  • chrome: set icons in manifest.json

with chrome as default

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.