如何复制静态文件建立目录与Webpack?

我试图从Gulp移动到Webpack。在Gulp中,我有一个任务,它将所有文件和文件夹从静态/文件夹复制到/构建/文件夹。如何对Webpack做同样的事情?我需要一些插件吗?

391536 次浏览

你不需要到处复制东西,webpack的工作方式与gulp不同。Webpack是一个模块捆绑器,你在文件中引用的所有内容都将被包括在内。你只需要为此指定一个加载器。

所以如果你写:

var myImage = require("./static/myImage.jpg");

Webpack将首先尝试将引用的文件解析为JavaScript(因为这是默认的)。当然,这将会失败。这就是为什么您需要为该文件类型指定一个加载器。例如,文件-或url-loader获取引用的文件,将其放入webpack的输出文件夹(在您的情况下应该是build),并返回该文件的散列url。

var myImage = require("./static/myImage.jpg");
console.log(myImage); // '/build/12as7f9asfasgasg.jpg'

通常加载器是通过webpack配置来应用的:

// webpack.config.js


module.exports = {
...
module: {
loaders: [
{ test: /\.(jpe?g|gif|png|svg|woff|ttf|wav|mp3)$/, loader: "file" }
]
}
};

当然,您需要首先安装文件加载器才能使其工作。

使用文件加载器模块要求资产是webpack打算使用的方式()。然而,如果你需要更大的灵活性或想要一个更干净的界面,你也可以直接使用我的copy-webpack-plugin (npmGithub)复制静态文件。对于你的staticbuild的例子:

const CopyWebpackPlugin = require('copy-webpack-plugin');
 

module.exports = {
context: path.join(__dirname, 'your-app'),
plugins: [
new CopyWebpackPlugin({
patterns: [
{ from: 'static' }
]
})
]
};

注意:兼容性如果你正在使用旧版本的webpack,比如webpack@4.x.x,使用copy-webpack-plugin@6.x.x。否则使用最新的。

如果你想复制静态文件,你可以这样使用文件加载器:

对于HTML文件:

在webpack.config.js中:

module.exports = {
...
module: {
loaders: [
{ test: /\.(html)$/,
loader: "file?name=[path][name].[ext]&context=./app/static"
}
]
}
};

在js文件中:

  require.context("./static/", true, /^\.\/.*\.html/);

./static/相对于js文件的位置。

你可以对图像或其他东西做同样的事情。 语境是一种强大的探索方法!!< / p >

最有可能的是,你应该使用CopyWebpackPlugin,这是在kevlened回答中提到的。另外,对于某些类型的文件,如. html. json,你也可以使用raw-loader或json-loader。通过npm install -D raw-loader安装它,然后你只需要向我们的webpack.config.js文件添加另一个加载器。

如:

{
test: /\.html/,
loader: 'raw'
}

注意:重启webpack-dev-server以使任何配置更改生效。

现在你可以要求html文件使用相对路径,这使得它更容易移动文件夹。

template: require('./nav.html')

以上建议都很好。但是为了直接回答你的问题,我建议在你的package.json中定义的脚本中使用cpy-cli

这个例子期望node在你路径上的某个地方。将cpy-cli安装为开发依赖项:

npm install --save-dev cpy-cli

然后创建两个nodejs文件。一个用于复制,另一个用于显示复选标记和消息。

copy.js

#!/usr/bin/env node


var shelljs = require('shelljs');
var addCheckMark = require('./helpers/checkmark');
var path = require('path');


var cpy = path.join(__dirname, '../node_modules/cpy-cli/cli.js');


shelljs.exec(cpy + ' /static/* /build/', addCheckMark.bind(null, callback));


function callback() {
process.stdout.write(' Copied /static/* to the /build/ directory\n\n');
}

checkmark.js

var chalk = require('chalk');


/**
* Adds mark check symbol
*/
function addCheckMark(callback) {
process.stdout.write(chalk.green(' ✓'));
callback();
}


module.exports = addCheckMark;

package.json中添加脚本。假设脚本在<project-root>/scripts/

...
"scripts": {
"copy": "node scripts/copy.js",
...

运行脚本:

npm run copy

你可以在package.json中编写bash:

# package.json
{
"name": ...,
"version": ...,
"scripts": {
"build": "NODE_ENV=production npm run webpack && cp -v <this> <that> && echo ok",
...
}
}

我也被困在这里了。Copy-webpack-plugin对我有用。

然而,'copy-webpack-plugin'在我的情况下是不必要的(我后来才知道)。

webpack忽略根路径
示例< / p >

<img src="/images/logo.png'>
因此,在不使用'copy-webpack-plugin'的情况下使其工作 在路径

中使用'~'
<img src="~images/logo.png'>

'~'告诉webpack将'images'视为一个模块

< p >注意: 您可能必须在

中添加images目录的父目录
resolve: {
modules: [
'parent-directory of images',
'node_modules'
]
}

访问https://vuejs-templates.github.io/webpack/static.html

webpack配置文件(在webpack 2中)允许你导出承诺链,只要最后一步返回一个webpack配置对象。参见承诺配置文档。从这里开始:

webpack现在支持从配置文件中返回Promise。这允许在配置文件中进行异步处理。

你可以创建一个简单的递归复制函数来复制你的文件,并且只在触发webpack之后。例如:

module.exports = function(){
return copyTheFiles( inpath, outpath).then( result => {
return { entry: "..." } // Etc etc
} )
}

让我们说你所有的静态资产都在一个文件夹“静态”在根级别,你想把它们复制到构建文件夹维护子文件夹的结构,然后 在你的入口文件中)只需输入

//index.js or index.jsx


require.context("!!file?name=[path][name].[ext]&context=./static!../static/", true, /^\.\/.*\.*/);
前面提到的copy-webpack-plugin带来的一个优点是,这里提到的所有其他方法仍然将资源捆绑到你的bundle文件中(并要求你“要求”或“导入”它们到某个地方)。如果我只是想移动一些图像或一些模板的部分,我不想用无用的引用来混乱我的javascript包文件,我只是想在正确的地方发出文件。我还没有在webpack中找到任何其他方法来做到这一点。不可否认,这不是webpack最初设计的目的,但它绝对是当前的用例。 (@BreakDS我希望这能回答你的问题-如果你想要它,这只是一个好处)

加载静态imagesfonts的方式:

module: {
rules: [
....


{
test: /\.(jpe?g|png|gif|svg)$/i,
/* Exclude fonts while working with images, e.g. .svg can be both image or font. */
exclude: path.resolve(__dirname, '../src/assets/fonts'),
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
}]
},
{
test: /\.(woff(2)?|ttf|eot|svg|otf)(\?v=\d+\.\d+\.\d+)?$/,
/* Exclude images while working with fonts, e.g. .svg can be both image or font. */
exclude: path.resolve(__dirname, '../src/assets/images'),
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
},
}
]
}

不要忘记安装file-loader来让它工作。

Webpack 5添加了资产模块,它本质上是普通文件加载器的替代品。我复制了以下文档的相关部分:

  • asset/resource生成一个单独的文件并导出URL。以前可以使用file-loader实现。
  • asset/inline导出资产的数据URI。以前可以使用url-loader实现。
  • asset/source导出资产的源代码。以前可以使用raw-loader实现。
  • asset自动在导出数据URI和发出单独的文件之间进行选择。以前可以通过使用带有资产大小限制的url-loader实现。

添加一个你可以使你的配置看起来像这样:

// webpack.config.js


module.exports = {
...
module: {
rules: [
{
test: /\.(jpe?g|gif|png|svg|woff|ttf|wav|mp3)$/,
type: "asset/resource"
}
]
}
};

要控制文件的输出方式,可以使用模板化路径

在配置中,你可以在这里设置全局模板:

// webpack.config.js
module.exports = {
...
output: {
...
assetModuleFilename: '[path][name].[hash][ext][query]'
}
}

为了覆盖一组特定的资产,你可以这样做:

// webpack.config.js


module.exports = {
...
module: {
rules: [
{
test: /\.(jpe?g|gif|png|svg|woff|ttf|wav|mp3)$/,
type: "asset/resource"
generator: {
filename: '[path][name].[hash][ext][query]'
}
}
]
}
};

提供的模板将产生类似build/images/img.151cfcfa1bd74779aadb.png的文件名。哈希可以用于缓存破坏等。你应该根据自己的需要进行修改。

文件版权是否正确

这里是这个线程的最终解决方案的图片和命令解释。

有时文件夹在复制过程中被覆盖,这就是出现文件夹错误的原因

https://stackoverflow.com/a/72959857/4452831 < a href = " https://stackoverflow.com/a/72959857/4452831 " > < / >

在我的例子中,我使用webpack作为wordpress插件来压缩js文件,其中插件文件已经被压缩了,需要跳过这个过程。

optimization: {
minimize: false,
},
externals: {
"jquery": "jQuery",
},
entry: glob.sync('./js/plugin/**.js').reduce(function (obj, el) {
obj[path.parse(el).name] = el;
return obj
}, {}),
output: {
path: path.resolve(__dirname, './js/dist/plugin'),
filename: "[name].js",
clean: true,
},

用于将js文件复制到build文件夹。使用任何其他方法,如文件加载器和复制webpack都会产生问题。

希望它能帮助到一些人。