cascornelissen / svg-spritemap-webpack-plugin

SVG spritemap plugin for webpack
MIT License
207 stars 49 forks source link

Issue with filename not the same on rebuild in manifest file #170

Closed xavianaxw closed 3 years ago

xavianaxw commented 3 years ago

Description

Greetings! Running into a little bit of a trouble with the spritemap plugin with manifest plugin not working too well together. tldr; with a configuration like so:

return {
  output: {
    filename: 'img/icons.svg',
    svg4everybody: config.svgSpritemapPlugin.svg4everybody,
    svgo: config.svgSpritemapPlugin.svgo,
  },
  sprite: {
    prefix: (filename) => {
      return filename.includes('icon-') ? '' : 'icon-';
    },
    generate: {
      title: false
    }
  }
};

It will output img/icons.svg/ in themanifest.jsonfile on first init but when I change any files in the folder we are passing through to the plugin, it will change fromimg/icons.svgtospritemap.svg` instead thus breaking the HMR setup I have with craft-twigpack.

Screen Shot 2021-07-11 at 4 22 25 pm

then after rebuild with watch mode

Screen Shot 2021-07-11 at 4 21 14 pm

Expected behavior Output should stay as img/icons.svg and not spritemap.svg in manifest file

Actual behavior Output is spritemap.svg

System information node v12.13.0

Minimal reproduction Currently don't have a repo currently but here are my package.json and webpack config

package.json

{
  "name": "bond-uni-website",
  "version": "1.0.0",
  "main": "index.js",
  "repository": "git@bitbucket.org:honest-fox/bond-uni-website.git",
  "author": "Xavian Ang <xavian@honestfox.com.au>",
  "license": "MIT",
  "scripts": {
    "dev": "webpack serve --config webpack.dev.js --mode=development",
    "build": "webpack --config webpack.prod.js --mode=production --progress --hide-modules",
    "svgo": "svgo -f src/icons"
  },
  "browserslist": {
    "production": [
      "> 1%",
      "last 2 versions",
      "Firefox ESR"
    ],
    "legacyBrowsers": [
      "> 1%",
      "last 2 versions",
      "Firefox ESR"
    ],
    "modernBrowsers": [
      "last 2 Chrome versions",
      "not Chrome < 60",
      "last 2 Safari versions",
      "not Safari < 10.1",
      "last 2 iOS versions",
      "not iOS < 10.3",
      "last 2 Firefox versions",
      "not Firefox < 54",
      "last 2 Edge versions",
      "not Edge < 15"
    ]
  },
  "devDependencies": {
    "@babel/core": "^7.14.6",
    "@babel/plugin-syntax-dynamic-import": "^7.8.3",
    "@babel/plugin-transform-runtime": "^7.14.5",
    "@babel/preset-env": "^7.14.7",
    "@babel/register": "^7.14.5",
    "@babel/runtime": "^7.14.6",
    "autoprefixer": "^10.3.0",
    "babel-loader": "^8.2.2",
    "css-loader": "^5.2.6",
    "dotenv": "^10.0.0",
    "file-loader": "^6.2.0",
    "postcss": "^8.3.5",
    "postcss-import": "^14.0.2",
    "postcss-loader": "^6.1.1",
    "postcss-scss": "^4.0.0",
    "sass": "^1.35.2",
    "sass-loader": "^12.1.0",
    "style-loader": "^3.0.0",
    "svg-spritemap-webpack-plugin": "^4.1.0",
    "svg4everybody": "^2.1.9",
    "svgo": "^2.3.1",
    "webpack": "^5.44.0",
    "webpack-cli": "^4.7.2",
    "webpack-dashboard": "^3.3.3",
    "webpack-dev-server": "^3.11.2",
    "webpack-manifest-plugin": "^3.1.1",
    "webpack-nano": "^1.1.1",
    "webpack-notifier": "^1.13.0"
  }
}

webpack.config.js

require('dotenv').config();

module.exports = {
  name: 'Project',

  entries: {
    app: 'app.js'
  },

  // paths to folders for our build system
  paths: {
    src: {
      base: './src/',
      css: './src/scss/',
      js: './src/js/',
      icons: './src/icons/',
    },
    dist: {
      base: './web/dist/',
      clean: ['**/*']
    },
    templates: './craft/templates/',
  },

  // dev server configuration
  // this will be overwritten depending on what is in .env
  devServer: {
    public: () => process.env.DEVSERVER_PUBLIC || 'http://localhost:8080',
    host: () => process.env.DEVSERVER_HOST || 'localhost',
    poll: () => process.env.DEVSERVER_POLL || false,
    port: () => process.env.DEVSERVER_PORT || 8080,
    https: () => process.env.DEVSERVER_HTTPS || false
  },

  /*
  ===============================================================================
    Loaders
  ===============================================================================
  */

  babelLoader: {
    exclude: [/(node_modules|bower_components)/]
  },

  /*
  ===============================================================================
    Plugins
  ===============================================================================
  */

  svgSpritemapPlugin: {
    svg4everybody: true,
    svgo: false,
  },

  manifestPlugin: {
    basePath: ''
  },
}

webpack.dev.js

const path = require('path');

// webpack plugins
const SVGSpritemapPlugin = require('svg-spritemap-webpack-plugin');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const WebpackNotifierPlugin = require('webpack-notifier');

// config files
const pkg = require('./package.json');
const config = require('./webpack.config.js');

// Configure Entries
const configureEntries = () => {
  let entries = {};
  for (const [key, value] of Object.entries(config.entries)) {
    entries[key] = path.resolve(__dirname, config.paths.src.js + value);
  }

  return entries;
};

// Configure the webpack-dev-server
const configureDevServer = () => {
  return {
    public: config.devServer.public(),
    contentBase: path.resolve(__dirname, config.paths.templates),
    host: config.devServer.host(),
    port: config.devServer.port(),
    https: !!parseInt(config.devServer.https()),
    disableHostCheck: true,
    hot: true,
    overlay: true,
    watchContentBase: true,
    watchOptions: {
      poll: !!parseInt(config.devServer.poll()),
      ignored: /node_modules/,
    },
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  };
};

/*
===============================================================================
  Loaders
===============================================================================
*/

// Configure Babel loader
const configureBabelLoader = browserList => {
  return {
    test: /\.js$/,
    exclude: config.babelLoader.exclude,
    use: {
      loader: 'babel-loader',
      options: {
        cacheDirectory: true,
        sourceType: 'unambiguous',
        presets: [
          [
            '@babel/preset-env',
            {
              modules: false,
              corejs: {
                version: 3,
                proposals: true
              },
              useBuiltIns: 'usage',
              targets: {
                browsers: browserList
              }
            }
          ]
        ],
        plugins: [
          '@babel/plugin-syntax-dynamic-import',
          '@babel/plugin-transform-runtime'
        ]
      }
    }
  };
};

const configureScssLoader = () => {
  return {
    test: /\.(scss)$/,
    include: [path.resolve(__dirname, config.paths.src.css)],
    use: [
      'style-loader',
      'css-loader',
      // 'resolve-url-loader',
      {
        loader: 'postcss-loader',
        options: {
          implementation: require('postcss'),
          sourceMap: true,
          postcssOptions: {
            config: path.resolve(__dirname),
          },
        },
      },
      {
        loader: 'sass-loader',
        options: {
          implementation: require('sass'),
          sourceMap: true,
          sassOptions: {
            indentWidth: 2,
            includePaths: ['node_modules/'],
          },
        },
      },
    ],
  };
};

// Configure font loader
// Configure vue/react loader

// Configure image loader
const configureImageLoader = () => {
  return {
    test: /\.(png|jpe?g|gif|svg|webp)$/i,
    use: [
      {
        loader: 'file-loader',
        options: {
          name: 'img/[name].[ext]',
        },
      },
    ],
  };
};

/*
===============================================================================
  Plugins
===============================================================================
*/

// Configure SVGSpritemap
const configureSVGSpritemapPlugin = () => {
  return {
    output: {
      filename: 'img/icons.svg',
      svg4everybody: config.svgSpritemapPlugin.svg4everybody,
      svgo: config.svgSpritemapPlugin.svgo,
    },
    sprite: {
      prefix: (filename) => {
        return filename.includes('icon-') ? '' : 'icon-';
      },
      generate: {
        title: false
      }
    }
  };
}

// Configure Manifest
const configureManifestPlugin = fileName => {
  return {
    fileName: fileName,
    basePath: config.manifestPlugin.basePath,
    map: file => {
      file.name = file.name.replace(/(\.[a-f0-9]{32})(\..*)$/, '$2');
      return file;
    }
  };
};

module.exports = () => {
  // mode is passed via CLI
  return {
    watch: true,
    entry: configureEntries(),
    target: 'web',
    devServer: configureDevServer(),
    devtool: 'inline-source-map',
    output: {
      filename: path.join('./js', '[name].js'),
      path: path.resolve(__dirname, config.paths.dist.base),
      publicPath: config.devServer.public() + '/',
    },
    module: {
      rules: [
        configureBabelLoader(Object.values(pkg.browserslist.modernBrowsers)),
        configureScssLoader(),
        configureImageLoader(),
      ],
    },
    plugins: [
      new WebpackNotifierPlugin({
        title: 'Webpack',
        excludeWarnings: true,
        alwaysNotify: true
      }),
      new SVGSpritemapPlugin(
        [path.resolve(__dirname, config.paths.src.icons, '**/*.svg')],
        configureSVGSpritemapPlugin()
      ),
      new WebpackManifestPlugin(configureManifestPlugin('manifest.json')),
    ],
  };
};

Steps to reproduce

  1. Add files to directory
  2. Run npm install or yarn install
  3. Create a folder src/icons and add some .svg files in them. Might need some other files like js/app.js as well
  4. Run npm run dev or yarn run dev
  5. Look at webpack-dev-server
  6. Create a new file or edit an existing .svg file
  7. Look at webpack-dev-server URL again and you can see the difference.
cascornelissen commented 3 years ago

This looks like the same issue as https://github.com/cascornelissen/svg-spritemap-webpack-plugin/issues/157 and https://github.com/cascornelissen/svg-spritemap-webpack-plugin/issues/157#issuecomment-808131853 should provide some additional details with a possible workaround.

I never heard back from the reporter of #157 so I'm not sure what the status/best way forward would be.

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.