webpack 配置 publicPath的理解

  学习webpack时,配置文件中有一个publicPath属性,一直不是很明白它到底是怎么用,也查了很多资料,得到最多的说法是当打包的时候,webpack会在静态文件路径前面添加publicPath的值,当我们把资源放到CDN上的时候,把publicPath的值设为CDN的值就可以了。但是在使用webpack 进行开发的时候,得到的结果却和该说法不是很一致,经过一段时间的摸索,好像是懂了一点点,至少在简单的配置中不会报错,在这里记一下,做一个总结.

  在开发环境下,通常是使用webpack-dev-server,因为它的热加载,实时更新。而在生产环境下,则是使用wepback命令进行打包,生成一个js 文件。上面publicPath的说法适用于生产环境。当使用webpack命令进行打包上生产时,它确实是在静态资源路径前面加上publicPath的值。 但在开发环境下,使用webpack-dev-server 进行开发时,它却不是在静态文件的路径上加publicPath的值,相反,它指的是webpack-dev-server 在进行打包时生成的静态文件所在的位置。也就是说publicPath在不同的环境下,有不同的意思。

  你可能有个疑问,webpack-dev-server会进行打包吗?是的,它会进行打包,代码只要有变动,它就会打包,只不过它打包到的地方是计算机的内存,而不是硬盘。那就有个问题,怎么才能访问到这些打包到内存中资源呢?不要忘了,webpack-dev-sever 也是一台运行在计算机内存中的服务器,把打包后的资源放到webpack-dev-server服务器下面,不就行了。放到服务器的什么地方,就是由publicPath决定的,同时,它也决定了怎么才能访问这些资源。默认情况下,publicPath 的取值是 '/', 也就是说,会把打包后的文件放到webpack-dev-server服务器的根目录下,文件名是在output配置中的filename. 如果配置了publicPath,webpack-dev-server 会把所有的文件打包到publicPath指定的目录下,相当于在项目根目录下创建了一个publicPath目录, 然后把打包后的文件放到了里面,只不过我们看不到而已, 文件名还是output配置中的filename。

  现在使用webpack验证一下。分两种情况,就是手动创建index.html文件 和使用html-webpack-plugin 自动创建index.html文件,效果明显一点。mkdir webpack-tut && cd webpack-tut && npm init -y。mkdir src 和 touch src/index.js。npm install webpack webpack-cli webpack-dev-server  --save-dev 来安装依赖. package.json中先写两个命令: 

"scripts": {
    "build": "webpack --mode production",
    "dev": "webpack server --mode development"
 },

  index.js 如下

document.body.innerHTML = "Hello World";

  由于webpack 4 提供了零配置,入口是src/index.js,输出文件在dist目录,文件名为main.js,可以不用写配置文件。

  手动创建index.html文件

  项目根目录中新建index.html,但怎么引入打包后的js文件,根据上面的分析,webpack-dev-server默认情况下,会把打包后的文件放到服务器根目录下,并且文件名应为 main.js, 所以index.html文件中引入js 应该为 src="./main.js"

<body>
    <script src="./main.js"></script>
</body>

  npm run dev , 打开浏览器,输入localhost:8080,  报错了,再看一下webpack-dev-server 打包信息,

   不是webpack打包生成的内容从public目录下面服务,也就是说要把index.html放到public目录下面,在根目录下面新建public, 放入index.html。npm run dev 重启服务器,刷新浏览器,可以看到页面显示了Hello World。再执行npm run build 进行打包,打包完成后,生成了dist目录,这时就会发现问题了,index.html 下面 './main.js' 是无法引入dist 下面的main.js的,所以要改成

<script src="../dist/main.js"></script>

  把dist目录删除,再npm run dev, 启动webpack-dev-server就会出问题,因为打包后文件会放到服务器根目录下,你访问服务器的dist目录,肯定没有,

  现在就要设置webpack-dev-server 的静态资源的服务路径是dist。这时要配置文件了,webpack.config.js

module.exports = {
    output: {
        publicPath: '/dist/'
    }
}

  npm run dev  启动webpack-dev-server , 在浏览器中输入localhost:8080  一切正常,没有错误, 这是为什么,看看webpack-dev-server的启动信息

  整个项目运行在localhost:8080下面, 这也就是在浏览器中输入localhost:8080,能访问到服务器的原因。当在浏览器中输入服务器地址,服务器会寻找它下面的index.html文件,并返回给浏览器,因为指定了index.html位置,所以能找到。浏览器接收到index.html 就开始解析,它碰到script标签就会向服务器请求js 文件,js的地址是dist/main.js,服务器就会在dist目录下找main.js.  根据我们所知道的,当有publicPath 配置时,webpack-dev-server 会把打包后的资源放到publicPath 指定的目录,也就是dist 目录下,所以服务器是在dist 目录下可以找到main.js,没有问题,整个项目也没有报错。

  接着向下看:wepback output is served from /dist/ , webpack 输出(打包后的文件)放到了/dist/ 目录下,这也证明了webpack-dev-server 进行打包时,它打包到了publicPath 指定的目录。

  现在我们知道了js等静态文件所在的地址和名称,可以尝试访问一下。在浏览器输入localhost:8080/dist/main.js, 看到main.js文件,这也证明了我们的分析是正确的。

  其实有一个办法,可以看到我们localhost服务器下的资源,也就是控制台中的source 面板。

  服务器下面有一个index.html 文件和dist 文件夹,这里也可以看到webpack-dev-server 打包生成了一个dist 文件夹。

  总结:当我们手动创建index.html, 并手动指定css 或js 静态文件路径时,保证path 和publicPath的设置一致就好了。

  自动创建index.html

  现在把public目录和index.html 删除,然后通过html-webpack-plugin 自动创建index.html。 npm install html-webpack-plugin --save-dev, webpack.config.js 修改如下

const htmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    output: {
        publicPath: '/dist/'
    },
    plugins: [
        new htmlWebpackPlugin() // 使用插件
    ]
}

   npm run dev,浏览器输入localhost:8080,报错了,因为配置了publicPath,当有publicPath的时候,webpack-dev-server 会把所有打包好的文件都放到publicPath 指定的目录下,也就是dist目录,因为index.html文件是由webpack 打包生成的,所以它也在dist 目录下,那么我们应该访问服务器下面的dist 目录,所以浏览器中应该输入localhost:8080/dist/index.html, 访问成功了。再看一下控制台中的source 面板,

  可以看到localhost 本地服务器下面只有一个dist 目录,dist 目录有打包好的静态资源,这也充分证明了,webpack-dev-server 会把所有的文件打包到publicPath指定的目录。这样访问有点不太方便了,webpack-dev-server把文件打包到服务器根目录下,localhost:8080就会访问到。去掉publicPath配置,重启服务器。

 

  没有问题。那么npm run build 打包到生产环境有没有问题呢?打包成功之后,可以发现没有问题。这是因为html和其它静态资源是在同一个文件下, html文件直接访问其它文件是不用加什么前缀路径

  总结一下,在使用html-webpack-plugin 生成index.html时,publicPath是可以不用配置的,使用默认配置就好

 

posted @ 2018-01-25 22:23  SamWeb  阅读(42724)  评论(6编辑  收藏  举报