在学习webpack的时候,配置文件中有一个publicPath属性,一直不是很明白它究竟是怎么用,也查了不少资料,获得最多的说法是当打包的时候,webpack会在静态文件路径前面添加publicPath的值,当咱们把资源放到CDN上的时候,把publicPath的值设为CDN的值就能够了。可是在使用webpack 进行开发的时候,获得的结果却和该说法不是很一致,通过一段时间的摸索,好像是懂了一点点,至少在简单的配置中不会报错,在这里记一下,作一个总结.css
咱们在使用webpack 进行开发的时候,一般是使用webpack-dev-server 进行开发,由于它的热加载,实时更新。而在生产上版本的时候,则是使用wepback命令进行打包,生成一个js 文件。上面的publicPath的使用说法适用于生产环境。当使用webpack命令进行打包上生产时,它确实是在静态资源路径前面加上publicPath的值。 可是当咱们使用webpack-dev-server 进行开发时,它却不是在静态文件的路径上加publicPath的值,相反,它指的是webpack-dev-server 在进行打包时生成的静态文件所在的位置。也就是说publicPath的使用是分环境的。html
你可能有个疑问,webpack-dev-server会进行打包吗?webpack-dev-server也会进行打包,代码只要一变更,它就会打包,只不过它打包到的地方是计算机的内存,在硬盘中看不到。再具体一点,默认状况下,webpack-dev-server 会把打包后的文件放到项目的根目录下,文件名是在output配置中的filename. 可是当有publicPath 配置的时候,就不同了。Webpack 会把全部的文件打包到publicPath指定的目录下,就是至关于在项目根目录下建立了一个publicPath目录, 而后把打包成的文件放到了它里面,只不过咱们看不到而已, 文件名仍是output配置中的filename。node
如今使用webpack验证一下。不过还要分两种状况,手动建立index.html文件 和html-webpack-plugin 自动建立index.html文件。手动建立html 不常见,可是我在初学webpack的时候,确实是手动建立index.html的,也是折腾了很久。无论哪一种状况,先把webpack 项目搭建起来.webpack
新建一个文件夹webpack-tut, 执行npm init -y, 建立package.json 文件,同时初始化为node 项目。再在里面新建 src 文件夹和webpack.config.js 配置文件。在src 里面再新建css文件夹,img文件夹,index.js。css 文件夹 有一个style.css 放置样式,在img文件夹中放置一大一小两张图片, 小的图片1kb, 大的图片5kb. index.js 做为入口文件,npm install webpack webpack-dev-server css-loader style-loader url-loader file-loader --save-dev 来安装依赖. package.json中先写两个命令: web
"scripts": { "build": "webpack", "dev":"webpack-dev-server" },
webpack.config.js 以下npm
const path = require('path'); module.exports = { entry: path.join(__dirname, 'src/index.js'), output: { path: path.join(__dirname, 'dist'), filename:'bundle.js' }, module: { rules:[ { test: /\.css$/, use: ['style-loader', 'css-loader'] }, { test: /\.(png|jpg)$/, loader: 'url-loader', options: { limit: 3000, name: '[name].[hash:8].[ext]' } } ] } }
style.css 以下:json
.small { width: 200px; height: 200px; background: url(../img/small.jpg) no-repeat; } .big { width: 500px; height: 350px; background: url(../img/big.jpg) no-repeat; }
index.js 以下浏览器
import './css/style.css'; import img from './img/big.jpg'; var imgElement = document.createElement('img'); imgElement.src = img; document.body.appendChild(imgElement);
手动建立index.html文件服务器
如今咱们在项目根目录中新建index.html, 整个index.html 以下app
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Webpack Tut</title> </head> <body> <div class="small"></div> <div class="big"></div> </body> </html>
如今最重要的问题是怎么引入打包后的js 文件,根据上面的分析,咱们能够知道,当启动webpack-dev-server的时候,它把打包后的文件放到根目录下,而且文件名应为 bundle.js, 因此index.html文件中引入js 应该为 src="./bundle.js"
<body> <div class="small"></div> <div class="big"></div> <script src="./bundle.js"></script> </body>
如今npm run dev 启动webpack-dev-server, 而后打开浏览器,输入localhost:8080, 能够看到三张图都显示出来了,没有问题,证实分析是正确的。
如今执行npm run build 进行打包, 打包完成后,以访问服务器的方式打开index.html,由于,打包后的文件是要发布到服务器上的。怎么使用这种方式 ?VS code 编辑器有一个扩展叫作Live Server,安装以后,在index.html中右键,有一个 open with Live Server选项, 点击,它会使用默认的浏览器以服务器的方式打开文件。这时你发现页面空白,确定是报错了,打开控制台,bundle.js 文件没有找到,这时想起来,bundle.js是打包到 dist 目录下,修改index.html ,引入dist 下面的js.
<script src="./dist/bundle.js"></script>
刷新浏览器,页面只有一张图片,大图并无显示出来,这是为何呢?打开控制台, 点击Elements 选项卡能够看到
咱们js动态插入的img图片,和class=big 的div的background, 它们都是引用的根目录下的图片,但根目录下并无这张图片,dist 目录下面有这张图片,咱们想要让它引用dist下面的图片, 这时想到webpack 进行打包的时候会把publicPath指定的路径加到静态资源路径前面, 因此在webpack的配置文件中加入publicPath
再执行npm run build从新打包,刷新浏览器,能够看到三张图片. 再打开浏览器台,能够看到img 的路径前面加了dist
这时咱们再来看看class=big的div的样式
咱们在style.css的源代码中是url(../img/big.jpg), 而在打包以后,它却把url的路径改为了dist, 由于打包后全部的静态图片都放到了dist 目录下,没有了 img 目录。
如今npm run dev 启动webpack-dev-server , 在浏览器中输入localhost:8080 一切正常,没有错误, 咱们来分析一下,这是为何,首先要看一下,当启动webpack-dev-server的时候,发生了什么
整个项目运行在localhost:8080下面,也就是服务器地址是localhost:8080 , 这也是咱们在浏览器中输入localhost:8080的缘由。当咱们在浏览器中输入服务器地址,服务器会寻找它下面的index.html文件,并返回给浏览器,由于咱们的项目在webpack-tut目录下启动的,它下面有index.html,这没有问题,浏览器在接受到index.html 就开始解析,它碰到script标签就会向服务器请求js 文件,js的地址是dist/bundle.js,服务器就会在dist目录下找bundle.js. 根据咱们所知道的,当有publicPath 配置时,webpack-dev-server 会把打包后的资源放到publicPath 指定的目录,也就是dist 目录下,因此服务器是在dist 目录下能够找到bundle.js,没有问题,整个项目也没有报错。分析完了,但仍是向下看一下吧,有意外的收获
接着向下看:wepback output is served from /dist/ , webpack 输出(打包后的文件)放到了/dist/ 目录下,这也证实了webpack-dev-server 进行打包时,它打包到了publicPath 指定的目录。
而后就没有什么重要的了,hash, verison,wepback 开始进行打包,最后是time, 表示耗时799ms, webpack 完成了打包,打包后的文件列出来了,一个img,名称为big.2a9adfd0.jpg,一个js 文件 bundle.js,还列了出打包所经历的各类module, 最后显示complied successful, 直到这时浏览器能够访问了。
如今咱们知道了js, img等静态文件所在的地址和名称,能够尝试访问一下。在浏览器输入localhost:8080/dist/bundle.js, 看到bundle.js文件,输入localhost:8080/dist/ big.2a9adfd0.jpg, 看到了图片,这也证实了咱们的分析是正确的。
其实有一个办法,能够看到咱们localhost服务器下的资源,也就是控制台中的source 面板。
服务器下面有一个index.html 文件和dist 文件夹,这里也能够看到webpack-dev-server 打包生成了一个dist 文件夹。
总结:当咱们手动建立index.html, 并手动指定css 或js 静态文件路径时,保证path 和publicPath的设置一致就行了。
自动建立index.html
如今把index.html 删除,而后经过html-webpack-plugin 自动建立index.html, 同时把dist 目录删掉。 npm install html-webpack-plugin --save-dev, webpack.config.js 修改以下
const path = require('path'); // 引入webpack 和 html-webpack-plugin插件 const webpack = require('webpack'); const htmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: path.join(__dirname, 'js/index.js'), output: { path: path.join(__dirname, 'dist'), filename:'bundle.js', publicPath: '/dist/' }, module: { rules:[ { test: /\.css$/, use: ['style-loader', 'css-loader'] }, { test: /\.(png|jpg)$/, loader: 'url-loader', options: { limit: 10000, name: '[name].[hash:8].[ext]' } } ] }, plugins: [ new htmlWebpackPlugin() // 使用插件 ] }
npm run dev 启动服务器,浏览器,输入localhost:8080,能够看到服务器下面,都没有index.html 这个文件
这是怎么一回事?看一下咱们的配置文件,配置了publicPath,当有publicPath的时候,webpack-dev-server 会把全部打包好的文件都放到publicPath 指定的目录下,也就是dist目录,由于index.html文件是由webpack 打包生成的,因此它也在dist 目录下,那么咱们应该访问服务器下面的dist 目录,因此浏览器中应该输入localhost:8080/dist/,
访问成功了。再看一下控制台中的source 面板,
能够看到localhost 本地服务器下面只有一个dist 目录,dist 目录有打包好的静态资源,这也充分证实了,webpack-dev-server 会把全部的文件打包到publicPath指定的目录。这样访问有点不太方便了,最简单的办法,就是把publicPath配置去掉,这样webpack-dev-server就会把文件打包到根目录下,localhost:8080就会访问到。去掉以后重启服务器。
没有问题。那么npm run build 打包到生产环境有没有问题呢?打包成功以后,能够发现没有问题。这是由于html和其它静态资源是在同一个文件下, html文件直接访问其它文件是不用加什么前缀路径
总结一下,在使用html-webpack-plugin 生成index.html时,publicPath是能够不用配置的。