设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 创业者 数据 手机
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

webpack高级配置与优化详解(3)

发布时间:2020-05-10 08:16 所属栏目:118 来源:站长网
导读:为什么 webpack 会存在跨域问题?因为 webpack 打包的是前端代码,其最终会被部署到前端服务器上,而前后端代码通常部署在不同的服务器上,即使是部署在同一个服务器上,所使用的端口也是不一样的,当前端代码通过

为什么 webpack 会存在跨域问题?因为 webpack 打包的是前端代码,其最终会被部署到前端服务器上,而前后端代码通常部署在不同的服务器上,即使是部署在同一个服务器上,所使用的端口也是不一样的,当前端代码通过 ajax 等手段向后端服务器获取数据的时候,由于前后端代码不在同一个域中,故存在跨域问题。

比如,我们通过 webpack 的 devServer 来运行部署我们的前端应用代码,devServer 启动在 8080 端口上,而前端应用代码中会通过 ajax 请求后端数据,后端服务器启动在 3000 端口上。

// index.js const xhr = new XMLHttpRequest(); // xhr.open("get", "http://localhost:3000/api/test"); // 由于跨域问题无法直接访问到:3000下的资源 xhr.open("get", "/api/test"); // 本来是要访问:3000/api/test xhr.onreadystatechange = () => { if (xhr.readyState === 4) { console.log(xhr.responseText); } } xhr.send();

由于前端代码是运行在浏览器中的,如果在前端代码中直接通过 ajax 向:3000/api/test 发起请求获取数据,那么由于浏览器同源策略的影响,会存在跨域的问题,所以必须访问 /api/test。但是这样访问又会出现 404 问题,因为其实访问的是 :8080/api/test,8080 服务器上是没有该资源的,解决办法就是通过 devServer 配置一个代理服务器

module.exports = { devServer: { proxy: { "/api": "http://localhost:3000" // 路径以/api开头则代理到localhost:3000上 } } }

访问 :8080/api/test 

就会被代理到:3000/api/test 上,proxy 还支持路径的重写,如果 3000 端口服务器上并没有 /api/test 路径,只有 /test 路径,那么就可以对路径进行重写,将 /api 替换掉

module.exports = { devServer: { proxy: { "/api": { target: "http://localhost:3000", pathRewrite: {"/api": ""} // 将/api替换掉 } } } }

访问 :8080/api/test 

就会被代理到 :3000/test 上

如果前端只是想 mock 一些数据,并不需要真正的去访问后台服务器,那么我们可以通过 devServer 提供的 before 钩子函数获取到内置的服务器对象进行处理请求,这个内置的服务器对象就是 webpack 的 devServer 即 8080 端口的 server,因为是在同一个服务器中请求数据所以也不会出现跨域问题。

before(app) { // 此app即webpack的devServer app.get("/api/test", (req, res, next) => { res.json({name: "even"}); }) }

我们还可以不通过 webpack 提供的 devServer 来启动 webpack,而是使用自己服务器来启动 webapck。

const express = require("express"); const app = express(); const webpack = require("webpack"); // 引入webpack const config = require("./webpack.config.js"); // 引入配置文件 const compiler = webpack(config); // 创建webpack的编译器 const middleWare = require("webpack-dev-middleware"); //引入webpack的中间件 app.use(middleWare(compiler)); // 将compiler编译器交给中间件处理 app.get("/api/test", (req, res, next) => { res.json({name: "lhb"}); }); app.listen(3000);

通过自定义服务器启动 webpack,这样 webpack 中的前端代码请求数据就和服务器的资源在同一个域中了。

六、resolve 配置

resolve 用于配置模块的解析相关参数的,其属性值为一个对象。

1、modules: 告诉 webpack 解析模块时应该搜索的目录,即 require 或 import 模块的时候,只写模块名的时候,到哪里去找,其属性值为数组,因为可配置多个模块搜索路径,其搜索路径必须为绝对路径,比如,src 目录下面有一个 foo.js 文件和 index.js 文件:

// index.js const foo = require("./foo"); // 必须写全foo.js模块的路径 // const foo = require("foo"); // resolve.modules中配置了模块解析路径为.src目录,则可用只写foo即可搜索到foo.js模块 console.log(foo); module.exports = { resolve: { modules: [path.resolve(__dirname, "./src/"), "node_modules"] }, }

由于 resolve.modules 中配置了 ./src 目录作为模块的搜索目录,所以 index.js 中可以只写模块名即可搜索到 foo.js 模块

2、alias: 用于给路径或者文件取别名,当 import 或者 require 的模块的路径非常长时,我们可以给该模块的路径或者整个路径名+文件名都设置成一个别名,然后直接引入别名即可找到该模块,比如,有一个模块位置非常深

// const foo = require("./a/b/c/foo"); // foo.js在./src/a/b/c/foo.js // const foo = require("foo"); // foo被映射成了./src/a/b/c/foo.js文件 const foo = require("bar/foo.js"); // bar被映射成了./src/a/b/c/路径 console.log(foo); module.exports = { resolve: { alias: { "foo": path.resolve(__dirname, "./src/a/b/c/foo.js"), "bar": path.resolve(__dirname, "./src/a/b/c/") } }, }

需要注意的就是,alias 可以映射文件也可以映射路径

3、mainFields: 我们的 package.json 中可以有多个字段,用于决定优先使用哪个字段来导入模块,比如 bootstrap 模块中含有 js 也含有 css,其 package.json 文件中 main 字段对应的是"dist/js/bootstrap",style 字段中对应的是"dist/css/bootstrap.css",我们可以通过设置 mainFields 字段来改变默认引入,如:

module.exports = { resolve: { mainFields: ["style", "main"] }, }

4、extensions: 用于设置引入模块的时候,如果没有写模块后缀名,webpack 会自动添加后缀去查找,extensions 就是用于设置自动添加后缀的顺序,如:

module.exports = { resolve: { extensions: ["js", "vue"] }, }

如果项目中引入了 foo 模块,require("./foo"),其会优先找 ./foo.js,如果没有找到 ./foo.js 则会去找 ./foo.vue 文件

七、设置环境变量

设置环境变量需要用到 webpack 提供的一个内置插件 DefinePlugin 插件,其作用是将一个字符串值设置为全局变量,如:

module.exports = { plugins: [ new webpack.DefinePlugin({ DEV_MODE: JSON.stringify('development') // 将'development'设置为全局变量DEV_MODE }), ] }

这样配置之后任何一个模块中都可以直接使用 DEV_MODE 变量了,并且其值为'development',与 ProvidePlugin 有点相似,ProvidePlugin 是将一个模块注入到所有模块中,实现模块不需要引入即可直接使用。

八、webpack 优化

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读