copy-webpack-plugin icon indicating copy to clipboard operation
copy-webpack-plugin copied to clipboard

globOptions.ignore not work expected

Open takeTrace opened this issue 2 years ago • 22 comments

Bug report

When I use Copy Plugin follow README, it does not work like README said. And I check issues, after use someone's method, it work, but not work well in sometimes;

Actual Behavior

I use Copy Plugin to copy dir public in my project root dir to webpack output path's dir public, And I follow the config in README's globOptions descriptionn

new CopyWebpackPlugin({
			patterns: [
				{
					from: "public/**/*",
					globOptions: {
						ignore: [
							"**/.DS_Store",
							"**/index.html",
							"**/asdasd.md",
						],
					},
				},
			],
		})

it doesn't work at all. plugin will copy all the files in public;

and after search I found here ignoring-files in Readme.

new CopyWebpackPlugin({
			patterns: [
				{
					from: path.posix.join(
						path.resolve(__dirname, "public").replace(/\\/g, "/"), "**/*"),
					globOptions: {
						ignore: [
							"**/.DS_Store",
							"**/index.html",
							"**/asdasd.md",
						],
					},
				},
			],
		})

but it doesn't work, still copy all files.

and I found something in issues, try #498 said that I add path.posix function to ignore property, it work, but only work on one file... if I specific more than one file use path.posix, it throw error

new CopyWebpackPlugin({
			patterns: [
				{
					from: "public/**/*",
					globOptions: {
						ignore: [
							"**/.DS_Store",
							path.posix.join(__dirname, "public/index.html"),
							// path.posix.join(__dirname, "public/asdasd.md"), //if open this. will throw following error 
							// `ERROR in unable to locate '/project-root-dir/public/**/*' glob`
						],
					},
				},
			],
		}),

Expected Behavior

It should ignore public/index.html and public/asdasd.md files when copy to webpack output folder.

How Do We Reproduce?

I create a demo repo. just run pnpm install && pnpm run build OR npm install && npm run build.

Please paste the results of npx webpack-cli info here, and mention other relevant information

System: OS: macOS 12.3.1 CPU: (8) x64 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz Memory: 38.72 MB / 16.00 GB Binaries: Node: 18.1.0 - ~/.nvs/default/bin/node Yarn: 1.22.18 - /usr/local/bin/yarn npm: 8.8.0 - ~/.nvs/default/bin/npm Browsers: Chrome: 100.0.4896.127 Firefox: 100.0 Safari: 15.4 Packages: copy-webpack-plugin: ^10.2.4 => 10.2.4 webpack: ^5.72.0 => 5.72.0 webpack-cli: ^4.9.2 => 4.9.2

takeTrace avatar May 06 '22 10:05 takeTrace

Sorry, problem is not in the plugin, all options from globOptions passed to fast-glob, so if something is not ignored, it means fast-glob is not ignore it

alexander-akait avatar May 06 '22 12:05 alexander-akait

same issue

copy-webpack-plugin @5.x

new CopyPlugin(
  [
    {
      from: 'public',
      to: '/XXX/dist',
      toType: 'dir',
      ignore: [
        '.DS_Store',
        {
          glob: 'index.html',
          matchBase: false
        }
      ]
    }
  ]
)

copy-webpack-plugin @11.x (ignore option not working)

new CopyWebpackPlugin({
  patterns: [
    {
      from: 'public',
      to: /XXX/dist,
      toType: 'dir',
      globOptions: {
        ignore: [ '.DS_Store', 'index.html' ]
      }
    }
  ]
})

ruokid avatar Jul 05 '22 04:07 ruokid

Please use **/.DS_Store for nested, docs here https://github.com/mrmlnc/fast-glob#ignore

alexander-akait avatar Jul 05 '22 04:07 alexander-akait

hi @alexander-akait

when i use it to build

new CopyWebpackPlugin({
  patterns: [
    {
      from: 'public',
      to: /XXX/dist,
      toType: 'dir',
      globOptions: {
        ignore: [ 'index.html' ]
      }
    }
  ]
}),
new HtmlWebpackPlugin({
  filename: 'index.html',
  template: 'public/index.html',
  title: projectName
})

I got

ERROR in Conflict: Multiple assets emit different content to the same filename index.html

now, if i use this

new CopyWebpackPlugin({
  patterns: [
    {
      from: 'public',
      to: /XXX/dist,
      toType: 'dir',
      globOptions: {
        ignore: [ '**/index.html' ]
      }
    }
  ]
}),
new HtmlWebpackPlugin({
  filename: 'index.html',
  template: 'public/index.html',
  title: projectName
})

i got

ERROR in unable to locate '/XXX/public/**/*' glob

and this is my directory image

ruokid avatar Jul 06 '22 07:07 ruokid

ERROR in Conflict: Multiple assets emit different content to the same filename index.html

It means you have multiple files with different content:

  1. You copy files with the same name in one directory (i.e. dir1/index.html and dir2/index.html => dist/index.html)
  2. You have html-webpack-plugin and copy index.html, the situation the same as above, just html-webpack-plugin creates index.html

alexander-akait avatar Jul 06 '22 14:07 alexander-akait

yes, so i need to ignore public/index.html, but globOptions.ignore not working

ruokid avatar Jul 07 '22 04:07 ruokid

Try to experiment, ignore is working, just with some limitations

alexander-akait avatar Jul 07 '22 14:07 alexander-akait

yes, so i need to ignore public/index.html, but globOptions.ignore not working

it's work for me. just add globalOptions-ignore [**/*.html],

my webpack.common.js

  new webpack.DefinePlugin({
      BASE_URL: JSON.stringify('/'),
    }),
    new HtmlWebpackPlugin({
      // 指定模板,此插件仍然会创建文件
      title: 'Typescript + Vue',
      template: '/public/index.html', // 如果使用自己的模板需要另外引入favicon图标
      //   favicon: '../public/favicon.ico',
    }),

    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, '../public'),
          to: path.resolve(__dirname, '../dist'),
          toType: 'dir',
          globOptions: {
            dot: false, // 允许匹配以 . 开头的文件, 比如 .gitignore
            gitignore: false,
            ignore: ['.DS_Store', '**/index.html'],
          },
        },
      ],
    }),

NOTE: html-webpack-plugin, default Specifying the template will also output the html file to the build directory, should you also specify the final output filename

PachVerb avatar Jul 09 '22 10:07 PachVerb

hi @alexander-akait

when i use it to build

new CopyWebpackPlugin({
  patterns: [
    {
      from: 'public',
      to: /XXX/dist,
      toType: 'dir',
      globOptions: {
        ignore: [ 'index.html' ]
      }
    }
  ]
}),
new HtmlWebpackPlugin({
  filename: 'index.html',
  template: 'public/index.html',
  title: projectName
})

I got

ERROR in Conflict: Multiple assets emit different content to the same filename index.html

now, if i use this

new CopyWebpackPlugin({
  patterns: [
    {
      from: 'public',
      to: /XXX/dist,
      toType: 'dir',
      globOptions: {
        ignore: [ '**/index.html' ]
      }
    }
  ]
}),
new HtmlWebpackPlugin({
  filename: 'index.html',
  template: 'public/index.html',
  title: projectName
})

i got

ERROR in unable to locate '/XXX/public/**/*' glob

and this is my directory image

I had the same problem

N-You avatar Oct 11 '22 05:10 N-You

It means globby can't find directory

alexander-akait avatar Oct 11 '22 11:10 alexander-akait

yes, so i need to ignore public/index.html, but globOptions.ignore not working

it's work for me. just add globalOptions-ignore [**/*.html],

my webpack.common.js

  new webpack.DefinePlugin({
      BASE_URL: JSON.stringify('/'),
    }),
    new HtmlWebpackPlugin({
      // 指定模板,此插件仍然会创建文件
      title: 'Typescript + Vue',
      template: '/public/index.html', // 如果使用自己的模板需要另外引入favicon图标
      //   favicon: '../public/favicon.ico',
    }),

    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, '../public'),
          to: path.resolve(__dirname, '../dist'),
          toType: 'dir',
          globOptions: {
            dot: false, // 允许匹配以 . 开头的文件, 比如 .gitignore
            gitignore: false,
            ignore: ['.DS_Store', '**/index.html'],
          },
        },
      ],
    }),

NOTE: html-webpack-plugin, default Specifying the template will also output the html file to the build directory, should you also specify the final output filename

兄弟我复制你的发现也不报错了,啥原理啊这是,我听着有点迷糊

wkz2003 avatar Feb 20 '23 17:02 wkz2003

yes, so i need to ignore public/index.html, but globOptions.ignore not working

it's work for me. just add globalOptions-ignore [**/*.html],

my webpack.common.js

  new webpack.DefinePlugin({
      BASE_URL: JSON.stringify('/'),
    }),
    new HtmlWebpackPlugin({
      // 指定模板,此插件仍然会创建文件
      title: 'Typescript + Vue',
      template: '/public/index.html', // 如果使用自己的模板需要另外引入favicon图标
      //   favicon: '../public/favicon.ico',
    }),

    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, '../public'),
          to: path.resolve(__dirname, '../dist'),
          toType: 'dir',
          globOptions: {
            dot: false, // 允许匹配以 . 开头的文件, 比如 .gitignore
            gitignore: false,
            ignore: ['.DS_Store', '**/index.html'],
          },
        },
      ],
    }),

NOTE: html-webpack-plugin, default Specifying the template will also output the html file to the build directory, should you also specify the final output filename

刚看错了,还是报错啊兄弟

wkz2003 avatar Feb 20 '23 17:02 wkz2003

I'm not sure I completely understand if this will help OP, but I wanted to ignore specific files in the from: directory (in my case, only ./static/index.html and not ./static/**/index.html. For people struggling with this like me, you might consider ditching globOptions and using filter instead. It's a predicate that takes the file's (absolute) path and returns a true or false to be copied or not.

This is how I got it to work:

patterns: [{ from: "./static", filter:(filepath) => {
    const ignorePaths = ['/static/index.html']
    const doCopy = ignorePaths.every(path => !filepath.endsWith(path))
     return doCopy;
} }]

For my case, since I am ignoring one file, a simple return !filePath.endsWith('/static/index.html') would be fine. In this code, you can add your filepath to ignorePaths and it will return false if the (absolute) filepath ends in any of the ignorePaths, true otherwise.

rendall avatar Feb 22 '23 08:02 rendall

I'm not sure I completely understand the OP, but I wanted to ignore specific files in the from: directory (in my case, only ./static/index.html and not ./static/**/index.html. For people struggling with this like me, you might consider ditching globOptions and using filter instead. It's a predicate that takes the file's (absolute) path and returns a true or false, whether you want it to be copied or not.

This is how I got it to work:

patterns: [{ from: "./static", filter:(filepath) => {
    const ignorePaths = ['/static/index.html']
    const doCopy = ignorePaths.every(path => !filepath.endsWith(path))
     return doCopy;
} }]

For my case, since I am ignoring one file, a simple return !filePath.endsWith('/static/index.html') would be fine. In this code, you can add your filepath to ignorePaths and it will return false if the (absolute) filepath ends in any of the ignorePaths, true otherwise.

I'm not sure I completely understand the OP, but I wanted to ignore specific files in the from: directory (in my case, only ./static/index.html and not ./static/**/index.html. For people struggling with this like me, you might consider ditching globOptions and using filter instead. It's a predicate that takes the file's (absolute) path and returns a true or false, whether you want it to be copied or not.

This is how I got it to work:

patterns: [{ from: "./static", filter:(filepath) => {
    const ignorePaths = ['/static/index.html']
    const doCopy = ignorePaths.every(path => !filepath.endsWith(path))
     return doCopy;
} }]

For my case, since I am ignoring one file, a simple return !filePath.endsWith('/static/index.html') would be fine. In this code, you can add your filepath to ignorePaths and it will return false if the (absolute) filepath ends in any of the ignorePaths, true otherwise.

oh! It's a good solution.The only shortcoming is I can't use cases like 'public/**.html',but I think I can use regex to fix that

wkz2003 avatar Feb 22 '23 16:02 wkz2003

Definitely! Something like

return /public\/.*\.html$/.test(filepath)

rendall avatar Feb 22 '23 18:02 rendall

      ignore: ['.DS_Store', '**/index.html'],

globalOptions.ignore seems only work on alone '**/index.html' but i can use fliter option hahaha.

realmxu avatar Mar 22 '23 16:03 realmxu

hi @alexander-akait ,I encountered the same problem as above. The plug-in version I use is 11.0.0. image image I tried to copy the contents of the public folder under the root directory to the webpack packaged folder, And ignore a.js, b.js, and index.html. When I ignore only a.js and index.html, it works normally, but when I ignore b.js at the same time, an error will be reported. image Could you explain the reason? thank you!

Sober-1 avatar Mar 25 '23 16:03 Sober-1

@Sober-1 hm, can you create reproducible test repo? it should work

alexander-akait avatar Mar 27 '23 15:03 alexander-akait

@alexander-akait I also did a test on my Mac and the same problem occurred

Sober-1 avatar Mar 27 '23 15:03 Sober-1

Do you have the public directory? If no (or if it will be created as a part of build) please try https://github.com/webpack-contrib/copy-webpack-plugin#noerroronmissing

alexander-akait avatar Mar 27 '23 16:03 alexander-akait

I used " noErrorOnMissing: true", Now the problem has been solved. thank you

Sober-1 avatar Mar 28 '23 02:03 Sober-1

Change index.html to **/public/index.html would work as expect.

fsjohnhuang avatar Apr 14 '23 06:04 fsjohnhuang