webpack 项目访问静态资源
使用 webpack dev serve 启动 react 项目后,发现无法使用 http://localhost:8080/1.png 访问到项目的 /static 目录下的 1.png 文件。我的 webpack-dev.js 配置如下:
const webpack = require('webpack')
const webpackMerge = require('webpack-merge')
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
const baseWebpackConfig = require('./webpack.config.base')
const proxy = require('../proxy/index.js')
const path = require('path')
const smp = new SpeedMeasurePlugin()
const config = webpackMerge.merge(baseWebpackConfig, {
mode: 'development', // 模式 默认两种 production development
devtool: 'cheap-module-eval-source-map',
plugins: [
new webpack.HotModuleReplacementPlugin() // 热更新插件
],
devServer: { // 开发服务器配置
hot: true,
port: 8080,
open: false,
quiet: false,
inline: true,
stats: 'errors-only',
overlay: false,
clientLogLevel: 'silent',
compress: true,
// contentBase: path.join(__dirname, 'dist'),
contentBase: path.join(__dirname, '../static'), // 设置开发服务器根目录
proxy: {
'/': {
bypass: function (req, res, proxyOptions) {
return `/index.html`
}
},
...proxy
}
}
})
module.exports = config
发现是 proxy 的配置下 把 访问 / 的路径全部拦截到 /index.html 下了,所以访问不到 /static 目录下的静态资源。
解决方案
改一下 proxy 的逻辑即可,修改后的 webpack-dev.js 配置:
const webpack = require('webpack')
const webpackMerge = require('webpack-merge')
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
const baseWebpackConfig = require('./webpack.config.base')
const proxy = require('../proxy/index.js')
const path = require('path')
const smp = new SpeedMeasurePlugin()
const config = webpackMerge.merge(baseWebpackConfig, {
mode: 'development', // 模式 默认两种 production development
devtool: 'cheap-module-eval-source-map',
plugins: [
new webpack.HotModuleReplacementPlugin() // 热更新插件
],
devServer: { // 开发服务器配置
hot: true,
port: 8080,
open: false,
quiet: false,
inline: true,
stats: 'errors-only',
overlay: false,
clientLogLevel: 'silent',
compress: true,
// contentBase: path.join(__dirname, 'dist'),
contentBase: path.join(__dirname, '../static'), // 设置开发服务器根目录
proxy: {
'/': {
bypass: function (req, res, proxyOptions) {
// 如果请求的是以 /static/resources 开头的路径,不做重定向,直接返回 null
if (req.url.startsWith('/resources')) {
return null; // 不重定向,继续处理静态资源
}
return `/index.html`
}
},
...proxy
}
}
})
module.exports = config
相关文档可以参考 webpack 官网 - proxy
继续展开
我发现我执行 npm run build 无法将 我的react项目跟目录下的 /static/resources/pdf/ 资源打包到 dist 目录中。
解决办法:
安装 copy-webpack-plugin@6.0.0 插件, 这个版本适配 webpack@4.41.5 这个版本,已经测试可用。
npm install copy-webpack-plugin@6.0.0
然后再 webpack.base.js 配置:
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
plugins: [
new CopyWebpackPlugin({
patterns: [
{ from: 'static/resources/pdf', to: 'static/resources/pdf' }
]
})
]
}
手动指定要复制的资源,这样执行 npm run build 之后就能将 /static/resources/pdf下的文件打包到 /dist/static/resources/pdf 目录下了。
继续展开
我有一个需求就是要将文档放在项目目录中,然后用户点击下载按钮,就找到项目中的对应文件下载。
代码如下:
function createAndRemove(url, fileName) {
// 创建 a 标签
var link= document.createElement('a');
// 下载内容转变成blob地址
link.href = process.env.INTERFACE_DOCUMENT + "a.pdf";
link.download = fileName;
// 触发点击
document.body.appendChild(link);
eleLink.click();
// 然后移除
document.body.removeChild(link);
}
为什么要用 process.env.INTERFACE_DOCUMENT 这个变量?
因为项目部署在本地(通过 npm start 启动) 和 部署到线上路径可能会不一样。
a.pdf 文件在项目的根目录下的 /static/resources/pdf/ , 访问路径为 http://localhost:8080/resources/pdf/a.pdf
项目打包后, a.pdf 会被打包到 /dist/static/resources/pdf/ , 部署到线上后,使用的 nginx 部署项目, nginx 的配置指定 dist 为根目录,
nginx.conf 配置如下
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
listen [::]:80;
server_name _;
#root /usr/share/nginx/html;
root /project;
location / {
root /dist;
index index.html index.htm;
try_files $uri $uri/ /index.html; # 解决页面路由问题,刷新页面返回 404
}
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
dist 目录结构为
|- dist
|-----static
|---------- img
|---------- css
|---------- js
|---------- resources
|-----------------pdf
此时线上访问 a.pdf 的路径为 http://ip:port/static/resources/pdf/a.pdf
所以才会有根据环境变量来获取 URL的这段代码 process.env.INTERFACE_DOCUMENT。
.env.development 文件
INTERFACE_DOCUMENT=/resources/pdf/
.env.production 文件
INTERFACE_DOCUMENT=/static/resources/pdf/
这样配置完后,在本地和在线上就都能够正常下载了。
注意:如果你的文件名为中文,部署到 linux 中,中文可能会乱码,会导致找不到文件,所以最好使用英文文件名。