Angular 6 SSR引入Bootstrap 4报错:Cannot set property 'emulateTransitionEnd' of undefined
我最近在Angular 6的SSR项目里引入了"bootstrap": "^4.1.1",结果运行node server.js的时候直接炸了,报了这么一堆错误:
!(function(t,e){true?e(exports,__webpack_require__(150),__webpack_require__(255)):undefined})(this,(function(t,e,c){"use strict";function i(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function o(t,e,n){return e&&i(t.prototype,e),n&&i(t,n),t}function h(r){for(var t=1;t<arguments.length;t++){var s=null!= arguments[t]?arguments[t]:{},e=Object.keys(s);"function"==typeof Object.getOwnPropertySymbols&&(e=e.concat(Object.getOwnPropertySymbols(s).filter((function(t){return Object.getOwnPropertyDescriptor(s,t).enumerable})))),e.forEach((function(t){var e,n,i;e=r,i=s[n=t],n in e?Object.defineProperty(e,n,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[n]=i}))}return r}e=e&&e.hasOwnProperty("default")?e.default:e ,c=c&&c.hasOwnProperty("default")?c.default:c;var r,n,s,a,l,u,f,d,_,g,m,p,v,E,y,T,C,I,A,D,b,S,w,N,O,k,P,L,j,R,H,W,M,x,U,K,F,V,Q,B,Y, TypeError: Cannot set property 'emulateTransitionEnd' of undefined at J:\Java\workstation\front\.server\server.js:3538:2584 at J:\Java\workstation\front\.server\server.js:3538:2745 at J:\Java\workstation\front\.server\server.js:3538:22 at Object.<anonymous> (J:\Java\workstation\front\.server\server.js:3538:94) at __webpack_require__ (J:\Java\workstation\front\.server.js:1:360) at Object.module.exports (J:\Java\workstation\front\.server.js:3484:10746) at __webpack_require__ (J:\Java\workstation\front\.server.js:1:360) at J:\Java\workstation\exhibition\front\.server\server.js:1:1654 at Object.<anonymous> (J:\Java\workstation\front\.server.js:1:1702) at Module._compile (module.js:643:30)
我的vendor.ts代码是这么写的:
window['jQuery'] = require('jquery'); window['$'] = window['jQuery']; import 'bootstrap/dist/js/bootstrap.min.js';
Webpack配置里也加了ProvidePlugin:
new webpack.ProvidePlugin({ $: 'jquery', jQuery: "jquery", "window.jQuery": "jquery" }),
有没有老哥能帮忙看看咋解决?
其实这个错很简单——Bootstrap在SSR的服务端环境里找不到jQuery!因为服务端是Node.js环境,根本没有window对象,你直接往window上挂jQuery自然没用。咱们一步步来搞定:
第一步:补全依赖
先确保你装了jquery和popper.js(Bootstrap 4必须要这俩),没装的话跑这个命令:npm install jquery popper.js --save第二步:只在客户端加载Bootstrap JS
服务端渲染不需要处理前端交互,所以Bootstrap的JS完全没必要在服务端加载。修改vendor.ts,加个环境判断:// 只有在浏览器环境(客户端)才加载jQuery和Bootstrap if (typeof window !== 'undefined') { window['jQuery'] = require('jquery'); window['$'] = window['jQuery']; require('bootstrap/dist/js/bootstrap.min.js'); }第三步:服务端Webpack排除Bootstrap
找到你的服务端Webpack配置文件(一般叫webpack.server.config.js),添加externals配置,告诉Webpack别把Bootstrap打包进服务端代码里:module.exports = { // ...其他配置项 externals: { jquery: 'jQuery', bootstrap: 'bootstrap' } };第四步:全局引入Bootstrap CSS
别忘了在angular.json的styles数组里加上Bootstrap的样式,不然页面没样式:"styles": [ "node_modules/bootstrap/dist/css/bootstrap.min.css", "src/styles.css" ]额外小建议:用Angular专属Bootstrap库
其实原生Bootstrap JS在SSR里很容易踩DOM相关的坑,不如直接用ng-bootstrap或者ngx-bootstrap——这俩是专门为Angular做的Bootstrap组件库,完全适配SSR,还不用手动处理jQuery依赖,省心多了!
内容的提问来源于stack exchange,提问作者Hadi Rasouli

