没办法wwWnudemv继续了,为何最进nudemvcom不能显示了

&h2&1. 本地代理&/h2&&p&比如利用 WebpackDevServer 配置本地代理&/p&&div class=&highlight&&&pre&&code class=&language-text&&devServer: {
port: 8080,
target: &http://other-server.example.com&
&/code&&/pre&&/div&&p&这样 `http://localhost:8080/api/getUser.php` 的请求就是后端的接口 `http://other-server.example.com/getUser.php`&/p&&h2&2. 浏览器配置&/h2&&p&以关闭浏览器安全策略的方式启动浏览器比如 Chrome:&/p&&div class=&highlight&&&pre&&code class=&language-text&&open -n /Applications/Google\ Chrome.app/ --args --disable-web-security
--user-data-dir
&/code&&/pre&&/div&&h2&3. JSONP&/h2&&p&本质上是利用 script 标签允许跨域。&/p&&p&如果你需要手写一个 JSONP 实现:&/p&&p&&a href=&//link.zhihu.com/?target=http%3A//blog.csdn.net/kumayato/article/details/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&手写一个jsonp - CSDN博客&/a&&/p&&p&&br&&/p&&h2&4. CORS &/h2&&p&&a href=&//link.zhihu.com/?target=http%3A//www.ruanyifeng.com/blog/2016/04/cors.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&跨域资源共享 CORS 详解 - 阮一峰的网络日志&/a&&/p&&p&&a href=&//link.zhihu.com/?target=https%3A//developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&HTTP访问控制(CORS)&/a&&/p&&p&&br&&/p&&h2&5.
document.domain&/h2&&p&&a href=&//link.zhihu.com/?target=http%3A//www.jb51.net/article/66497.htm& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&js设置document.domain实现跨域的注意点分析&/a&&/p&&p&&br&&/p&&h2&6. window.name&/h2&&p&&a href=&//link.zhihu.com/?target=https%3A//www.cnblogs.com/zichi/p/4620656.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&利用window.name+iframe跨域获取数据详解 - 韩子迟 - 博客园&/a&&/p&&p&&br&&/p&&h2&7. postMessage 实现跨域&/h2&&p&[HTML5 postMessage 传输与 POST 跨域通讯](&a href=&//link.zhihu.com/?target=https%3A//juejin.im/entry/59476fea128fedc& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&HTML5 postMessage 传输与 POST 跨域通讯&/a&)&/p&&p&&/p&
1. 本地代理比如利用 WebpackDevServer 配置本地代理devServer: {
port: 8080,
target: "http://other-server.example.com"
}这样 `http://localhost:8080/api/getUser.php` 的请求就是后端的接口 `http://other-server.examp…
&p&最近因为项目的需求,需要自定义HTML视频播放器样式。&/p&&p&因为之前没有接触过这方面的东西,所以第一感觉这个需求无非就是更改样式,实现的步骤无非就是将原生的video标签display:none之后,然后自己写一个控制面板,上面一堆按钮,包括播放、进度条、音量、倍速、进度条等,然后相应的东西调用对应的API即可&/p&&p&但是遇到了两个问题——&/p&&p&1.原生video标签的东西不好动&/p&&p&这要从它的DOM结构说起,先贴图&/p&&figure&&img src=&https://pic1.zhimg.com/v2-ad96daa01_b.jpg& data-size=&normal& data-rawwidth=&791& data-rawheight=&293& class=&origin_image zh-lightbox-thumb& width=&791& data-original=&https://pic1.zhimg.com/v2-ad96daa01_r.jpg&&&figcaption&可能有点不清楚,见谅,关键是红框&/figcaption&&/figure&&p&如图两个红框是原生video标签中的隐藏DOM,可以看见这两个东东还是嵌套的,最里层的隐藏DOM改动起来会很麻烦&/p&&p&2.如果跨浏览器兼容性会很不好,不能保持样式一致。&/p&&p&于是我们走上了第二条路——video.js&/p&&p&我对video.js的理解就是video.js把原生video标签里的内容拆成了一个一个组件,包括隐藏DOM里的东西,然后方便自定义使用,其次就是解决兼容性问题(这一点是最重要的我却没有使用进去,惭愧。。。)&/p&&p&video.js是开源插件,要使用video.js要做三件事——&/p&&p&第一、引入相关的css、js文件&/p&&p&第二、在video标签里添加class—— video-js、vjs-default-skin(这是最基本的两个,其中video-js是最重要的,其余的配置可以通过class的形式也可以在配置的js文件中)&/p&&p&第三、激活video.js(也就是实例化一个video.js)&/p&&p&&br&&/p&&p&当播放器出现这样的样式的时候,就说明video.js使用成功了&/p&&figure&&img src=&https://pic4.zhimg.com/v2-06f0bbdcbdf5c7bc0ee8377_b.jpg& data-size=&normal& data-rawwidth=&800& data-rawheight=&330& class=&origin_image zh-lightbox-thumb& width=&800& data-original=&https://pic4.zhimg.com/v2-06f0bbdcbdf5c7bc0ee8377_r.jpg&&&figcaption&没错,就是一个巨大的播放按钮在左上角&/figcaption&&/figure&&figure&&img src=&https://pic4.zhimg.com/v2-bf1c019d0dd283afc412c66b3ca2e562_b.jpg& data-size=&normal& data-rawwidth=&1357& data-rawheight=&511& class=&origin_image zh-lightbox-thumb& width=&1357& data-original=&https://pic4.zhimg.com/v2-bf1c019d0dd283afc412c66b3ca2e562_r.jpg&&&figcaption&这个是播放时候的样式&/figcaption&&/figure&&p&但是——新的风暴已经出现&/p&&p&使用的是angularJS框架,实例化video.js的时候会报错,提示找不到你要实例化的那个东西(id),原因是实例化的时候相关的DOM还没有生成,自然会报错,解决方式自然是写一个延迟函数,但这样的话就会有一个明显的延迟,相当不友好,所以我们可以把实例化的过程写到指令里面,这样从执行过程中来说就解决了报错的问题还解决了video加载明显延迟的问题。&/p&&p&但是,没错,还是有问题,因为现在都是单页面应用,当你从一个视频切换到另一个视频的时候,页面中只是更新了部分视图,也就是说video.js觉得自己已经实例化过了,而实则新的video标签并没有被实例化,解决这种情况的方式自然是手动刷新一下页面~&/p&&p&不不不,手动刷新怕是要被leader打死,自然是在自定义指令中做一些小小的操作,video.js有一个dispose方法用于手动清除,每次实例化之前先检查一下是否已经实例化,如果有就手动清除一次即可。&/p&&p&还有关于样式,一些固定的控件可以在实例化的时候通过提供的API调整,比如默认的音量样式是水平的,想要调整为纵向的可以通过这样的方式调整:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&//音量条竖直
controlBar: {
volumePanel: {
inline: false,
CurrentTimeDisplay: true
&/code&&/pre&&/div&&p&一些控件的细节可以自己写css调整&/p&&p&如果想创建没有的控件,比如说这次需求里的调整倍速,自己添加一个DOM元素然后绑定相应的事件,调用video.js提供的API即可。&/p&&p&&br&&/p&&p&最后贴一张最终实现的效果图&/p&&figure&&img src=&https://pic4.zhimg.com/v2-4fc3f09b17ddad_b.jpg& data-size=&normal& data-rawwidth=&598& data-rawheight=&330& class=&origin_image zh-lightbox-thumb& width=&598& data-original=&https://pic4.zhimg.com/v2-4fc3f09b17ddad_r.jpg&&&figcaption&没错,就是要求在视频播放前控制面板常驻,答应我,不要吐槽UI&/figcaption&&/figure&&p&对了,还有示例Demo&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&nx&&angular&/span&&span class=&p&&.&/span&&span class=&nx&&module&/span&&span class=&p&&(&/span&&span class=&s1&&'myApp'&/span&&span class=&p&&).&/span&&span class=&nx&&directive&/span&&span class=&p&&(&/span&&span class=&s1&&'videoPlayer'&/span&&span class=&p&&,&/span&&span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&$timeout&/span&&span class=&p&&,&/span& &span class=&nx&&$rootScope&/span&&span class=&p&&){&/span&
&span class=&k&&return&/span&&span class=&p&&{&/span&
&span class=&nx&&restrict&/span&&span class=&o&&:&/span&&span class=&s2&&&C&&/span&&span class=&p&&,&/span&
&span class=&nx&&link&/span&&span class=&o&&:&/span&&span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&scope&/span&&span class=&p&&,&/span&&span class=&nx&&ele&/span&&span class=&p&&,&/span&&span class=&nx&&attrs&/span&&span class=&p&&){&/span&
&span class=&nx&&$timeout&/span&&span class=&p&&(&/span&&span class=&kd&&function&/span& &span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&kd&&var&/span& &span class=&nx&&idName&/span& &span class=&o&&=&/span& &span class=&nx&&attrs&/span&&span class=&p&&.&/span&&span class=&nx&&id&/span&&span class=&p&&;&/span&
&span class=&c1&&//$rootScope.player——将player设置为根作用域,每次重新解析videoJs&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&$rootScope&/span&&span class=&p&&.&/span&&span class=&nx&&player&/span&&span class=&p&&){&/span&
&span class=&nx&&$rootScope&/span&&span class=&p&&.&/span&&span class=&nx&&player&/span&&span class=&p&&.&/span&&span class=&nx&&dispose&/span&&span class=&p&&();&/span&
&span class=&p&&}&/span&
&span class=&c1&&//实例化的过程&/span&
&span class=&nx&&$rootScope&/span&&span class=&p&&.&/span&&span class=&nx&&player&/span& &span class=&o&&=&/span& &span class=&nx&&videojs&/span&&span class=&p&&(&/span&&span class=&nx&&idName&/span&&span class=&p&&,&/span& &span class=&p&&{&/span&
&span class=&c1&&//音量条竖直&/span&
&span class=&nx&&controlBar&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&volumePanel&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&inline&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&CurrentTimeDisplay&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&p&&},&/span& &span class=&kd&&function&/span& &span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&c1&&//定义倍速按钮——按照音量模块为模板&/span&
&span class=&kd&&var&/span& &span class=&nx&&newbtn&/span& &span class=&o&&=&/span& &span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&createElement&/span&&span class=&p&&(&/span&&span class=&s1&&'btn'&/span&&span class=&p&&);&/span&
&span class=&nx&&newbtn&/span&&span class=&p&&.&/span&&span class=&nx&&innerHTML&/span& &span class=&o&&=&/span& &span class=&s1&&'&div class=&vjs-volume-panel vjs-control speedside&&&button class=&vjs-mute-control vjs-button vjs-vol-3 & type=&button&&&span id=&speed-video&&1X&/span&&/button&&div class=&vjs-volume-control vjs-control vjs-volume-vertical video-bar& id=&speedtab&&&/div&&/div&'&/span&&span class=&p&&;&/span&
&span class=&kd&&var&/span& &span class=&nx&&controlBar&/span& &span class=&o&&=&/span& &span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&getElementsByClassName&/span&&span class=&p&&(&/span&&span class=&s1&&'vjs-control-bar'&/span&&span class=&p&&)[&/span&&span class=&mi&&0&/span&&span class=&p&&];&/span&
&span class=&kd&&var&/span& &span class=&nx&&insertBeforeNode&/span& &span class=&o&&=&/span& &span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&getElementsByClassName&/span&&span class=&p&&(&/span&&span class=&s1&&'vjs-fullscreen-control'&/span&&span class=&p&&)[&/span&&span class=&mi&&0&/span&&span class=&p&&];&/span&
&span class=&nx&&controlBar&/span&&span class=&p&&.&/span&&span class=&nx&&insertBefore&/span&&span class=&p&&(&/span&&span class=&nx&&newbtn&/span&&span class=&p&&,&/span& &span class=&nx&&insertBeforeNode&/span&&span class=&p&&);&/span&
&span class=&c1&&//生成倍速选项、添加点击事件、增加选中样式&/span&
&span class=&k&&for&/span& &span class=&p&&(&/span&&span class=&kd&&let&/span& &span class=&nx&&i&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&p&&,&/span& &span class=&nx&&j&/span& &span class=&o&&=&/span& &span class=&mf&&0.5&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span& &span class=&o&&&&/span& &span class=&mi&&5&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span&&span class=&o&&++&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&kd&&var&/span& &span class=&nx&&newchoose&/span& &span class=&o&&=&/span& &span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&createElement&/span&&span class=&p&&(&/span&&span class=&s1&&'span'&/span&&span class=&p&&);&/span&
&span class=&kd&&var&/span& &span class=&nx&&newtext&/span& &span class=&o&&=&/span& &span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&createTextNode&/span&&span class=&p&&(&/span&&span class=&nx&&j&/span& &span class=&o&&+&/span& &span class=&s1&&'x'&/span&&span class=&p&&);&/span&
&span class=&nx&&newchoose&/span&&span class=&p&&.&/span&&span class=&nx&&appendChild&/span&&span class=&p&&(&/span&&span class=&nx&&newtext&/span&&span class=&p&&);&/span&
&span class=&nx&&newchoose&/span&&span class=&p&&.&/span&&span class=&nx&&className&/span& &span class=&o&&=&/span& &span class=&s1&&'speed'&/span&&span class=&p&&;&/span&
&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&getElementById&/span&&span class=&p&&(&/span&&span class=&s2&&&speedtab&&/span&&span class=&p&&).&/span&&span class=&nx&&appendChild&/span&&span class=&p&&(&/span&&span class=&nx&&newchoose&/span&&span class=&p&&);&/span&
&span class=&nx&&newchoose&/span&&span class=&p&&.&/span&&span class=&nx&&onclick&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span& &span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&nx&&$rootScope&/span&&span class=&p&&.&/span&&span class=&nx&&player&/span&&span class=&p&&.&/span&&span class=&nx&&playbackRate&/span&&span class=&p&&(&/span&&span class=&nx&&j&/span& &span class=&o&&-&/span& &span class=&mf&&0.25&/span&&span class=&p&&);&/span&
&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&getElementById&/span&&span class=&p&&(&/span&&span class=&s1&&'speed-video'&/span&&span class=&p&&).&/span&&span class=&nx&&innerHTML&/span& &span class=&o&&=&/span& &span class=&nx&&$rootScope&/span&&span class=&p&&.&/span&&span class=&nx&&player&/span&&span class=&p&&.&/span&&span class=&nx&&playbackRate&/span&&span class=&p&&()&/span& &span class=&o&&+&/span& &span class=&s1&&'x'&/span&&span class=&p&&;&/span&
&span class=&kd&&var&/span& &span class=&nx&&arrs&/span& &span class=&o&&=&/span& &span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&getElementsByClassName&/span&&span class=&p&&(&/span&&span class=&s1&&'speed'&/span&&span class=&p&&);&/span&
&span class=&k&&for&/span& &span class=&p&&(&/span&&span class=&kd&&let&/span& &span class=&nx&&k&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&p&&;&/span& &span class=&nx&&k&/span& &span class=&o&&&&/span& &span class=&nx&&arrs&/span&&span class=&p&&.&/span&&span class=&nx&&length&/span&&span class=&p&&;&/span& &span class=&nx&&k&/span&&span class=&o&&++&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&nx&&arrs&/span&&span class=&p&&[&/span&&span class=&nx&&k&/span&&span class=&p&&].&/span&&span class=&nx&&className&/span& &span class=&o&&=&/span& &span class=&s1&&'speed'&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&k&&this&/span&&span class=&p&&.&/span&&span class=&nx&&className&/span& &span class=&o&&=&/span& &span class=&s1&&'speed speedsidechoose'&/span&&span class=&p&&;&/span&
&span class=&p&&};&/span&
&span class=&nx&&j&/span& &span class=&o&&+=&/span& &span class=&mf&&0.25&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&c1&&//默认1x是选中样式&/span&
&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&getElementsByClassName&/span&&span class=&p&&(&/span&&span class=&s1&&'speed'&/span&&span class=&p&&)[&/span&&span class=&mi&&2&/span&&span class=&p&&].&/span&&span class=&nx&&className&/span& &span class=&o&&=&/span& &span class=&s1&&'speed speedsidechoose'&/span&&span class=&p&&;&/span&
&span class=&nx&&$rootScope&/span&&span class=&p&&.&/span&&span class=&nx&&player&/span&&span class=&p&&.&/span&&span class=&nx&&removeChild&/span&&span class=&p&&(&/span&&span class=&s1&&'BigPlayButton'&/span&&span class=&p&&);&/span&&span class=&c1&&//开始的大按钮&/span&
&span class=&nx&&$&/span&&span class=&p&&(&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&getElementById&/span&&span class=&p&&(&/span&&span class=&nx&&idName&/span&&span class=&p&&)).&/span&&span class=&nx&&css&/span&&span class=&p&&(&/span&&span class=&s2&&&zoom&&/span&&span class=&p&&,&/span& &span class=&s2&&&1.25&&/span&&span class=&p&&);&/span&
&span class=&nx&&$&/span&&span class=&p&&(&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&getElementById&/span&&span class=&p&&(&/span&&span class=&nx&&idName&/span&&span class=&p&&)).&/span&&span class=&nx&&css&/span&&span class=&p&&(&/span&&span class=&s2&&&width&&/span&&span class=&p&&,&/span& &span class=&s2&&&100%&&/span&&span class=&p&&);&/span&
&span class=&k&&if&/span&&span class=&p&&(&/span& &span class=&nx&&$&/span&&span class=&p&&(&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&getElementById&/span&&span class=&p&&(&/span&&span class=&nx&&idName&/span&&span class=&p&&)).&/span&&span class=&nx&&width&/span&&span class=&p&&()&/span&&span class=&o&&&&/span&&span class=&mi&&700&/span&&span class=&p&&){&/span&
&span class=&nx&&$&/span&&span class=&p&&(&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&getElementById&/span&&span class=&p&&(&/span&&span class=&nx&&idName&/span&&span class=&p&&)).&/span&&span class=&nx&&css&/span&&span class=&p&&(&/span&&span class=&s2&&&height&&/span&&span class=&p&&,&/span& &span class=&s2&&&414px&&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&k&&else&/span&&span class=&p&&{&/span&
&span class=&nx&&$&/span&&span class=&p&&(&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&getElementById&/span&&span class=&p&&(&/span&&span class=&nx&&idName&/span&&span class=&p&&)).&/span&&span class=&nx&&css&/span&&span class=&p&&(&/span&&span class=&s2&&&height&&/span&&span class=&p&&,&/span& &span class=&s2&&&305.5px&&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&cm&&/*让控制面板在视频未开始之前常驻*/&/span&
&span class=&nx&&$timeout&/span&&span class=&p&&(&/span&&span class=&kd&&function&/span&&span class=&p&&(){&/span&
&span class=&nx&&$&/span&&span class=&p&&(&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&getElementById&/span&&span class=&p&&(&/span&&span class=&nx&&idName&/span&&span class=&p&&)).&/span&&span class=&nx&&addClass&/span&&span class=&p&&(&/span&&span class=&s2&&&vjs-has-started&&/span&&span class=&p&&);&/span&
&span class=&p&&},&/span&&span class=&mi&&100&/span&&span class=&p&&);&/span&
&span class=&p&&});&/span&
&span class=&p&&})&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&p&&})&/span&
&/code&&/pre&&/div&&p&&br&&/p&&p&大概就是这样了,很多不足,还望包含。&/p&
最近因为项目的需求,需要自定义HTML视频播放器样式。因为之前没有接触过这方面的东西,所以第一感觉这个需求无非就是更改样式,实现的步骤无非就是将原生的video标签display:none之后,然后自己写一个控制面板,上面一堆按钮,包括播放、进度条、音量、倍…
&figure&&img src=&https://pic2.zhimg.com/v2-00aba0dcf2aa_b.jpg& data-rawwidth=&640& data-rawheight=&426& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic2.zhimg.com/v2-00aba0dcf2aa_r.jpg&&&/figure&&blockquote&&i&「阅」——JSCourse 旗下栏目,专门推荐我们为大家精心挑选的优质 JavaScript 相关技术内容&/i&&/blockquote&&p&一般大家都会有在 GitHub 上看某个项目源代码的需求:比方说你看到一个开源项目,想要深入了解下它是怎么工作的,就会上去看它的代码。&/p&&p&说到看代码,一般最直接的当然是直接在 GitHub 上看,这种方法要是遇到的项目代码文件内容不长的还好,要是文件内容很长、代码量比较大、特别是文件比较多的时候,就非常的不方便。通常也就 &code&cmd/ctrl+f&/code& 大法(查找变量定义、方法定义、或者这个变量在哪里用到了)能够一定程度上带来一点便利,但总体而言,这样看代码比较费劲。&/p&&p&还有就是会采用 &code&git clone&/code&,把代码直接拉到本地,用自己最熟悉的编辑器打开。我相信碰到复杂点的代码,大家都会倾向于选择这种方式。&/p&&p&小编最近发现了一款浏览器插件,它的名字叫:&a href=&http://link.zhihu.com/?target=https%3A//github.com/pd4d10/octohint& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&octohint&/a&。有了它,就可以相对比较方便的直接在 GitHub 上面阅读源代码了。&/p&&p&我们来看下官方的一个演示:&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-aa17b354d65abcc0a1d0d2b09c92018d_b.jpg& data-size=&normal& data-thumbnail=&https://pic2.zhimg.com/v2-aa17b354d65abcc0a1d0d2b09c92018d_b.jpg& class=&content_image&&&figcaption&来自:https://github.com/pd4d10/octohint&/figcaption&&/figure&&p&尽管没有像 VSC 这类编辑器那么强大,但是对于在线看代码还是很有帮助的,起码你查找变量就不用那么麻烦了,简单多了。&/p&&p&这款浏览器插件支持 Chrome、Firefox、Opera 和 Safari,另外其智能提示功能支持 &b&TypeScript&/b&、&b&JavaScript&/b&、&b&CSS&/b&、&b&LESS&/b& 以及 &b&SCSS&/b&,小编觉得基本满足我们的需求了。&/p&&p&而且它不止支持 GitHub,还支持 &b&Bitbucket&/b& 和 &b&GitLab&/b&,私有库也都是支持的。如果你觉得对你有帮助的话,不妨去试试吧!&/p&&p&好了,本期就到这里了,祝大家圣诞节快乐!我们下期再见咯!&/p&&p&&br&&/p&&p&关注「jscourse」微信公众号获取更多 JS 学习课程和资料!&/p&
「阅」——JSCourse 旗下栏目,专门推荐我们为大家精心挑选的优质 JavaScript 相关技术内容一般大家都会有在 GitHub 上看某个项目源代码的需求:比方说你看到一个开源项目,想要深入了解下它是怎么工作的,就会上去看它的代码。说到看代码,一般最直接的当…
&figure&&img src=&https://pic3.zhimg.com/v2-eda24fec98dc045afeb5_b.jpg& data-rawwidth=&5184& data-rawheight=&3456& class=&origin_image zh-lightbox-thumb& width=&5184& data-original=&https://pic3.zhimg.com/v2-eda24fec98dc045afeb5_r.jpg&&&/figure&&p&Brunch是这样一个构建工具:编译项目比Webpack更快,生成的dist文件更小并且项目配置更加容易。&/p&&p&在本文中,我将展示如何开发Vue.js + Brunch项目,并且涵盖Brunch的一些优缺点。&/p&&p&为了激发胃口,请先对比下相同Vue.js项目的Webpack配置和Brunch配置:&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-baf5fb660a106dadf1a1c406e66b269f_b.jpg& data-rawwidth=&4244& data-rawheight=&3128& class=&origin_image zh-lightbox-thumb& width=&4244& data-original=&https://pic2.zhimg.com/v2-baf5fb660a106dadf1a1c406e66b269f_r.jpg&&&/figure&&h2&Webpack&/h2&&p&Webpack是构建复杂,高度优化的Web应用程序的关键工具,并受到许多有影响力的Web开发者的推崇。&/p&&p&然而,对于新手开发者来说,Webpack是一个巨大的障碍。开发Vue.js项目时,用户会使用ES6,单文件组件。在这种复杂的环境中开发,在配置上需要花费不少时间。&/p&&h2&关注Brunch&/h2&&p&Brunch开始于2012年,它是Phoenix Elixir框架的默认构建工具,所以它只有一个小众的用户群,它的核心理念是“简单和快速”,这和Vue.js不谋而合。&/p&&p&在开源社区中,Brunch大约有80个插件,如代码提示、优化等。Brunch可以做在Vue项目中的大部分配置工作,比如将文件作为模块,自动化构建,编译Vue文件和SASS等。&/p&&p&还需要了解的是,Brunch不像Webpack那么功能齐全,其本身有一定的限制。例如,它不支持dynamic import,也不能不处理图像和字体。&/p&&h2&简约的配置&/h2&&p&使用Brunch,仅需要几行就可以完成配置。&/p&&p&在Webpack中,一个典型的SASS配置如下所示:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&nx&&module&/span&&span class=&p&&.&/span&&span class=&nx&&exports&/span& &span class=&o&&=&/span& &span class=&p&&{&/span&
&span class=&p&&...&/span&
&span class=&nx&&module&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&rules&/span&&span class=&o&&:&/span& &span class=&p&&[{&/span&
&span class=&nx&&test&/span&&span class=&o&&:&/span& &span class=&sr&&/\.scss$/&/span&&span class=&p&&,&/span&
&span class=&nx&&use&/span&&span class=&o&&:&/span& &span class=&p&&[{&/span&
&span class=&nx&&loader&/span&&span class=&o&&:&/span& &span class=&s2&&&style-loader&&/span&
&span class=&p&&},&/span& &span class=&p&&{&/span&
&span class=&nx&&loader&/span&&span class=&o&&:&/span& &span class=&s2&&&css-loader&&/span&
&span class=&p&&},&/span& &span class=&p&&{&/span&
&span class=&nx&&loader&/span&&span class=&o&&:&/span& &span class=&s2&&&sass-loader&&/span&
&span class=&p&&}]&/span&
&span class=&p&&}]&/span&
&span class=&p&&}&/span&
&span class=&p&&};&/span&
&/code&&/pre&&/div&&p&但是在Brunch中,你需要做的仅仅是安装Brunch的SASS插件。Brunch将遍历package.json,然后接管你安装的插件。&/p&&h2&Brunch测试&/h2&&p&为了看Brunch可以做什么,我已经使用Vue CLI初始化了一个Vue.js项目。在使用Webpack构建样板代码之后,我得到:&/p&&figure&&img src=&https://pic4.zhimg.com/v2-d925da8b59ebb2f572ee24062f80ebff_b.jpg& data-rawwidth=&2017& data-rawheight=&1227& class=&origin_image zh-lightbox-thumb& width=&2017& data-original=&https://pic4.zhimg.com/v2-d925da8b59ebb2f572ee24062f80ebff_r.jpg&&&/figure&&p&现在,我将要把该项目迁移到Brunch。&/p&&h2&安装&/h2&&p&建议将Brunch全局安装:&/p&&div class=&highlight&&&pre&&code class=&language-powershell&&&span&&/span&&span class=&n&&npm&/span& &span class=&n&&i&/span& &span class=&n&&-g&/span& &span class=&n&&brunch&/span&
&/code&&/pre&&/div&&h2&配置&/h2&&p&Brunch与Webpack有类似的声明性配置。以下是使Brunch运行的最小配置。它目前所做的就是将watch目录中的所有JavaScript文件模块化并合并最后输出到app.js。&/p&&p&&i&brunch-config.js&/i&&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&nx&&module&/span&&span class=&p&&.&/span&&span class=&nx&&exports&/span& &span class=&o&&=&/span& &span class=&p&&{&/span&
&span class=&nx&&files&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&javascripts&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&joinTo&/span&&span class=&o&&:&/span& &span class=&s1&&'app.js'&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&p&&};&/span&
&/code&&/pre&&/div&&p&与Webpack不同,Brunch不需要入口文件。相反,你只需要一个被观察目录,Brunch将自动处理该文件夹下的文件。&/p&&h2&构建&/h2&&p&先build:&/p&&div class=&highlight&&&pre&&code class=&language-powershell&&&span&&/span&&span class=&n&&brunch&/span& &span class=&n&&build&/span&
&/code&&/pre&&/div&&p&然后它将输出如下信息:&/p&&blockquote&14:32:19 - info: compiled main.js into app.js, copied logo.png in 466 ms&/blockquote&&p&然后一个名叫“public”的文件夹被创建,其内容如下:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&public
- app.js.map
- logo.png
&/code&&/pre&&/div&&h2&JavaScript构建文件&/h2&&p&然后我们来看看JavaScript的主要构建文件“public / app.js”,前149行是Brunch引导代码,每次构建都会存在。之后是main.js中的代码,是watch文件夹中唯一的JavaScript文件:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&nx&&require&/span&&span class=&p&&.&/span&&span class=&nx&&register&/span&&span class=&p&&(&/span&&span class=&s2&&&main.js&&/span&&span class=&p&&,&/span& &span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&exports&/span&&span class=&p&&,&/span& &span class=&nx&&require&/span&&span class=&p&&,&/span& &span class=&nx&&module&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&kr&&import&/span& &span class=&nx&&Vue&/span& &span class=&nx&&from&/span& &span class=&s1&&'vue'&/span&
&span class=&kr&&import&/span& &span class=&nx&&App&/span& &span class=&nx&&from&/span& &span class=&s1&&'./App.vue'&/span&
&span class=&k&&new&/span& &span class=&nx&&Vue&/span&&span class=&p&&({&/span&
&span class=&nx&&el&/span&&span class=&o&&:&/span& &span class=&s1&&'#app'&/span&&span class=&p&&,&/span&
&span class=&nx&&render&/span&&span class=&o&&:&/span& &span class=&nx&&h&/span& &span class=&o&&=&&/span& &span class=&nx&&h&/span&&span class=&p&&(&/span&&span class=&nx&&App&/span&&span class=&p&&)&/span&
&span class=&p&&})&/span&
&span class=&p&&});&/span&
&/code&&/pre&&/div&&p&Brunch使用Common.js模块包含main.js,它没有导入vue或App.vue,但没有使用ES5的语法。&/p&&h2&其它文件&/h2&&p&Brunch的另一个优点是,任何名为assests的目录都将被递归地复制到公用文件夹,而无需任何配置。&/p&&p&Brunch加载图像和字体文件的方式和Webpack不一样,所以最好把这些静态文件夹复制到输出文件夹。&/p&&h2&插件&/h2&&p&要处理项目文件,我需要添加一些插件到Brunch。比如ES6代码和包含SAAS的vue文件:&/p&&div class=&highlight&&&pre&&code class=&language-powershell&&&span&&/span&&span class=&p&&$&/span& &span class=&n&&npm&/span& &span class=&n&&i&/span& &span class=&p&&-&/span&&span class=&n&&-save-dev&/span& &span class=&n&&babel-brunch&/span& &span class=&n&&babel-preset-es2015&/span& &span class=&n&&vue-brunch&/span& &span class=&n&&sass-brunch&/span&
&/code&&/pre&&/div&&p&我还安装了babel-preset-es2015,所以需要更新.babelrc文件:&/p&&p&&i&.babelrc&/i&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&{
&presets&: [
[ &es2015& ]
&/code&&/pre&&/div&&p&这就搞定了,不用像Webpack那样写大量的配置代码。&/p&&p&当再次build的时候,输出了如下信息:&/p&&blockquote&15:05:57 - info: compiled 4 files into app.js, copied logo.png in 1.5 sec&/blockquote&&p&检查build文件“public / app.js”,发现代码变多了。这是因为Brunch在main.js中发现了ES6、Vue的依赖等。&/p&&p&&b&Brunch直接遍历了package.json并自动化的注册了这些插件。&/b&&/p&&h2&服务器托管&/h2&&p&和Webpack一样,Brunch也有一个开发服务器可供使用,使用起来相当简单:&/p&&div class=&highlight&&&pre&&code class=&language-powershell&&&span&&/span&&span class=&p&&$&/span& &span class=&n&&brunch&/span& &span class=&n&&watch&/span& &span class=&p&&-&/span&&span class=&n&&-server&/span&
&/code&&/pre&&/div&&p&运行之后终端会输入如下信息:&/p&&blockquote&15:16:40 - info: application started on http://localhost:3333/&br&15:16:40 - info: compiled 4 files into app.js, copied 2 in 1.7 sec&/blockquote&&h2&文件入口&/h2&&p&当我打开浏览器的时候,发现是一片空白,这是因为没有入口文件。&/p&&p&请记住Brunch是用Commonjs模块引入文件的:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&nx&&require&/span&&span class=&p&&.&/span&&span class=&nx&&register&/span&&span class=&p&&(&/span&&span class=&s2&&&main.js&&/span&&span class=&p&&,&/span& &span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&exports&/span&&span class=&p&&,&/span& &span class=&nx&&require&/span&&span class=&p&&,&/span& &span class=&nx&&module&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&c1&&// Contents of main.js&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&在浏览器中下载脚本后,还需要在index.html中调用该模块:&/p&&div class=&highlight&&&pre&&code class=&language-html&&&span&&/span&&span class=&p&&&&/span&&span class=&nt&&body&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&div&/span& &span class=&na&&id&/span&&span class=&o&&=&/span&&span class=&s&&&app&&/span&&span class=&p&&&&/&/span&&span class=&nt&&div&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&script&/span& &span class=&na&&type&/span&&span class=&o&&=&/span&&span class=&s&&&text/javascript&&/span& &span class=&na&&src&/span&&span class=&o&&=&/span&&span class=&s&&&/app.js&&/span&&span class=&p&&&&/&/span&&span class=&nt&&script&/span&&span class=&p&&&&/span&
&span class=&p&&&&/span&&span class=&nt&&script&/span& &span class=&na&&type&/span&&span class=&o&&=&/span&&span class=&s&&&text/javascript&&/span&&span class=&p&&&&/span&&span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'main'&/span&&span class=&p&&);&/&/span&&span class=&nt&&script&/span&&span class=&p&&&&/span&
&span class=&p&&&/&/span&&span class=&nt&&body&/span&&span class=&p&&&&/span&
&/code&&/pre&&/div&&p&&br&&/p&&h2&vue-brunch&/h2&&p&刷新浏览器后报了如下错误:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&Uncaught Error: Cannot find module 'vueify/lib/insert-css' from 'App.vue'
&/code&&/pre&&/div&&p&这是因为Brunch的插件API不如Webpack那么强大,为了能够在运行时内联CSS,vue-brunch需要使用vueify-insert-css模块。&/p&&p&这需要在main.js的顶部导入:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kr&&import&/span& &span class=&s1&&'vueify/lib/insert-css'&/span&&span class=&p&&;&/span&
&/code&&/pre&&/div&&p&都做完之后,我们可以看到vue.js项目启动成功了:&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-d925da8b59ebb2f572ee24062f80ebff_b.jpg& data-rawwidth=&2017& data-rawheight=&1227& class=&origin_image zh-lightbox-thumb& width=&2017& data-original=&https://pic4.zhimg.com/v2-d925da8b59ebb2f572ee24062f80ebff_r.jpg&&&/figure&&p&&br&&/p&&h2&生产环境配置&/h2&&p&在将Brunch与Webpack进行比较之前,还需要设置一些生产环境优化,这样做是为了保证这两种方法都产生等效的输出。&/p&&p&Webpack可以关闭开发模式输出的一些恶心的信息,Brunch也可以:&/p&&p&&i&main.js&/i&&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kr&&import&/span& &span class=&nx&&Vue&/span& &span class=&nx&&from&/span& &span class=&s1&&'vue'&/span&&span class=&p&&;&/span&
&span class=&nx&&Vue&/span&&span class=&p&&.&/span&&span class=&nx&&config&/span&&span class=&p&&.&/span&&span class=&nx&&productionTip&/span& &span class=&o&&=&/span& &span class=&kc&&false&/span&&span class=&p&&;&/span&
&/code&&/pre&&/div&&p&Brunch还支持uglify.js:&/p&&div class=&highlight&&&pre&&code class=&language-powershell&&&span&&/span&&span class=&p&&$&/span& &span class=&n&&npm&/span& &span class=&n&&i&/span& &span class=&p&&-&/span&&span class=&n&&-save-dev&/span& &span class=&n&&brunch-uglify-js&/span&
&/code&&/pre&&/div&&p&最后我们执行以下命令进行构建:&/p&&div class=&highlight&&&pre&&code class=&language-powershell&&&span&&/span&&span class=&p&&$&/span& &span class=&n&&brunch&/span& &span class=&n&&build&/span& &span class=&n&&-p&/span&
&/code&&/pre&&/div&&p&&br&&/p&&h2&对比&/h2&&p&&i&webpack.config.js&/i&&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&var&/span& &span class=&nx&&path&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'path'&/span&&span class=&p&&)&/span&
&span class=&kd&&var&/span& &span class=&nx&&webpack&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'webpack'&/span&&span class=&p&&)&/span&
&span class=&nx&&module&/span&&span class=&p&&.&/span&&span class=&nx&&exports&/span& &span class=&o&&=&/span& &span class=&p&&{&/span&
&span class=&nx&&entry&/span&&span class=&o&&:&/span& &span class=&s1&&'./src/main.js'&/span&&span class=&p&&,&/span&
&span class=&nx&&output&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&path&/span&&span class=&o&&:&/span& &span class=&nx&&path&/span&&span class=&p&&.&/span&&span class=&nx&&resolve&/span&&span class=&p&&(&/span&&span class=&nx&&__dirname&/span&&span class=&p&&,&/span& &span class=&s1&&'./dist'&/span&&span class=&p&&),&/span&
&span class=&nx&&publicPath&/span&&span class=&o&&:&/span& &span class=&s1&&'/dist/'&/span&&span class=&p&&,&/span&
&span class=&nx&&filename&/span&&span class=&o&&:&/span& &span class=&s1&&'build.js'&/span&
&span class=&p&&},&/span&
&span class=&nx&&module&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&rules&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&
&span class=&p&&{&/span&
&span class=&nx&&test&/span&&span class=&o&&:&/span& &span class=&sr&&/\.vue$/&/span&&span class=&p&&,&/span&
&span class=&nx&&loader&/span&&span class=&o&&:&/span& &span class=&s1&&'vue-loader'&/span&&span class=&p&&,&/span&
&span class=&nx&&options&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&loaders&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&c1&&// Since sass-loader (weirdly) has SCSS as its default parse mode, we map&/span&
&span class=&c1&&// the &scss& and &sass& values for the lang attribute to the right configs here.&/span&
&span class=&c1&&// other preprocessors should work out of the box, no loader config like this necessary.&/span&
&span class=&s1&&'scss'&/span&&span class=&o&&:&/span& &span class=&s1&&'vue-style-loader!css-loader!sass-loader'&/span&&span class=&p&&,&/span&
&span class=&s1&&'sass'&/span&&span class=&o&&:&/span& &span class=&s1&&'vue-style-loader!css-loader!sass-loader?indentedSyntax'&/span&
&span class=&p&&}&/span&
&span class=&c1&&// other vue-loader options go here&/span&
&span class=&p&&}&/span&
&span class=&p&&},&/span&
&span class=&p&&{&/span&
&span class=&nx&&test&/span&&span class=&o&&:&/span& &span class=&sr&&/\.js$/&/span&&span class=&p&&,&/span&
&span class=&nx&&loader&/span&&span class=&o&&:&/span& &span class=&s1&&'babel-loader'&/span&&span class=&p&&,&/span&
&span class=&nx&&exclude&/span&&span class=&o&&:&/span& &span class=&sr&&/node_modules/&/span&
&span class=&p&&}&/span&
&span class=&p&&]&/span&
&span class=&p&&},&/span&
&span class=&nx&&resolve&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&alias&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&s1&&'vue$'&/span&&span class=&o&&:&/span& &span class=&s1&&'vue/dist/vue.esm.js'&/span&
&span class=&p&&}&/span&
&span class=&p&&},&/span&
&span class=&nx&&devServer&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&historyApiFallback&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&&span class=&p&&,&/span&
&span class=&nx&&noInfo&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&
&span class=&p&&},&/span&
&span class=&nx&&performance&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&hints&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&
&span class=&p&&},&/span&
&span class=&nx&&devtool&/span&&span class=&o&&:&/span& &span class=&s1&&'#eval-source-map'&/span&
&span class=&p&&}&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&process&/span&&span class=&p&&.&/span&&span class=&nx&&env&/span&&span class=&p&&.&/span&&span class=&nx&&NODE_ENV&/span& &span class=&o&&===&/span& &span class=&s1&&'production'&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&nx&&module&/span&&span class=&p&&.&/span&&span class=&nx&&exports&/span&&span class=&p&&.&/span&&span class=&nx&&devtool&/span& &span class=&o&&=&/span& &span class=&s1&&'#source-map'&/span&
&span class=&c1&&// http://vue-loader.vuejs.org/en/workflow/production.html&/span&
&span class=&nx&&module&/span&&span class=&p&&.&/span&&span class=&nx&&exports&/span&&span class=&p&&.&/span&&span class=&nx&&plugins&/span& &span class=&o&&=&/span& &span class=&p&&(&/span&&span class=&nx&&module&/span&&span class=&p&&.&/span&&span class=&nx&&exports&/span&&span class=&p&&.&/span&&span class=&nx&&plugins&/span& &span class=&o&&||&/span& &span class=&p&&[]).&/span&&span class=&nx&&concat&/span&&span class=&p&&([&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&DefinePlugin&/span&&span class=&p&&({&/span&
&span class=&s1&&'process.env'&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&NODE_ENV&/span&&span class=&o&&:&/span& &span class=&s1&&'&production&'&/span&
&span class=&p&&}&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&optimize&/span&&span class=&p&&.&/span&&span class=&nx&&UglifyJsPlugin&/span&&span class=&p&&({&/span&
&span class=&nx&&sourceMap&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&&span class=&p&&,&/span&
&span class=&nx&&compress&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&warnings&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&
&span class=&p&&}&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&LoaderOptionsPlugin&/span&&span class=&p&&({&/span&
&span class=&nx&&minimize&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&
&span class=&p&&})&/span&
&span class=&p&&])&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&&br&&/p&&p&&i&brunch-config.js&/i&&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&nx&&module&/span&&span class=&p&&.&/span&&span class=&nx&&exports&/span& &span class=&o&&=&/span& &span class=&p&&{&/span&
&span class=&nx&&files&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&javascripts&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&joinTo&/span&&span class=&o&&:&/span& &span class=&s1&&'app.js'&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&p&&};&/span&
&/code&&/pre&&/div&&p&&br&&/p&&p&结果显而易见,Brunch用更少的代码完成了一样的功能。&/p&&p&&br&&/p&&h2&编译结果&/h2&&figure&&img src=&https://pic4.zhimg.com/v2-44f8ad29ef657cef1a86c8b53ac8e404_b.jpg& data-rawwidth=&741& data-rawheight=&126& class=&origin_image zh-lightbox-thumb& width=&741& data-original=&https://pic4.zhimg.com/v2-44f8ad29ef657cef1a86c8b53ac8e404_r.jpg&&&/figure&&p&很明显,Brunch编译出来的文件更小,速度更快。&/p&&p&&br&&/p&&h2&结论&/h2&&p&我认为Brunch是简单Vue项目的绝佳选择。它不仅容易设置,而且更快且提供了更小的生产环境代码。&/p&&p&但是,这不意味着让你用Brunch彻底替代Webpack。Brunch有许多事情不能做,例如dynamic imports,这对编写PWA应用至关重要。&/p&&p&如果感兴趣的话可以查看 &u&&a href=&https://link.zhihu.com/?target=http%3A//brunch.io/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Brunch docs&/a& &/u& 或 &u&&a href=&https://link.zhihu.com/?target=https%3A//github.com/brunch/brunch-guide& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&community guide&/a&&/u& 。&/p&&p&&/p&&p&&/p&&p&&/p&
Brunch是这样一个构建工具:编译项目比Webpack更快,生成的dist文件更小并且项目配置更加容易。在本文中,我将展示如何开发Vue.js + Brunch项目,并且涵盖Brunch的一些优缺点。为了激发胃口,请先对比下相同Vue.js项目的Webpack配置和Brunch配置: WebpackW…
&figure&&img src=&https://pic2.zhimg.com/v2-7ebb3cbf98fa9ef97079efd_b.jpg& data-rawwidth=&600& data-rawheight=&448& class=&origin_image zh-lightbox-thumb& width=&600& data-original=&https://pic2.zhimg.com/v2-7ebb3cbf98fa9ef97079efd_r.jpg&&&/figure&&blockquote&&h2&引言&/h2&&a href=&https://zhuanlan.zhihu.com/ucloud& class=&internal&&大U的技术课堂&/a& 的新年第一课,祝大家新的一年好好学习,天天向上:)&br&&br&本篇将手把手教你如何快速而优雅的构建&b&前后端分离的项目&/b&,想直接上手请往后翻!&/blockquote&&br&&p&&b&目录:&/b&&/p&&ol&&li&我为什么要选择Django与VueJS?&/li&&li&Django和VueJS是如何结合起来的?&/li&&li&实操&/li&&ol&&li&创建 Django 项目&/li&&li&创建 Django App 做为后端&/li&&li&创建 VueJS 项目作为前端&/li&&li&使用 Webpack 处理前端代码&/li&&li&配置 Django 模板的搜索路径&/li&&li&配置 Django 静态文件搜索路径&/li&&li&开发环境&/li&&li&生产环境(部署到 UCloud)&/li&&/ol&&/ol&&br&&br&&p&&b&正文:&/b&&/p&&h2&我为什么要选择Django与VueJS?&/h2&&p&首先介绍一下我看重的点:&/p&Django (MVC框架)
- &a href=&https://link.zhihu.com/?target=https%3A//www.djangoproject.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&The Web framework for perfectionists with deadlines&/a&&ul&&li&Python&br&&/li&&li&ORM&/li&&li&简单、清晰的配置&/li&&li&Admin app&/li&&/ul&Django 仅因为 Python 的血统,就已经站在了巨人的肩膀上,配置管理( SaltStack、Ansible )&br&,数据分析( Pandas ),任务队列( Celery ),Restful API( &a href=&https://link.zhihu.com/?target=http%3A//www.django-rest-framework.org/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Django REST framework&/a& ),HTTP请求( requests ),再加上高度抽象的ORM,功能强大的 Query Expressions,简单清晰的配置,着重提一下堪称神器的自带App: Admin,有了它你再也不用将一些经常变化的配置写在文件里面,每次增删改都重新发布一次,你只需要定义出配置的 data scheme ,只需要几行代码,Django Admin便为你提供美观,并带有权限控制的增删改查界面,而且可以通过ORM为它生成的API来做到定制化的更新,比如直接读某个wiki上的配置,自动的写入数据库,伪代码如下:&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&import pandas as pd
settings = pd.read_html('http://某个gitlab的README 或者 某个redmine wiki')
settings = clean(settings)
update(settings)
&/code&&/pre&&/div&&p&最后还可以使用 django-celery 的 celery-beat 按 Interval/crontab 的方式扔更新配置的任务到 celery 队列里面,最最重要的是,这些都可以在Django Admin后台直接配置哦,还不够优雅?请联系我&/p&&br&&br&&br&&p&VueJS (MVVM框架) - &a href=&https://link.zhihu.com/?target=https%3A//vuejs.org/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Vue.js&/a&&/p&&ul&&li&数据双向绑定&/li&&li&单文件组件&/li&&li&清晰的生命周期&/li&&li&学习曲线平滑&/li&&li&vue-cli&/li&&/ul&&blockquote&前端是DevOps的弱项,我需要一个 MVVM 框架来提升交互和节约时间,在试过 AngularJS ,ReactJS,VueJS之后我选择了VueJS,因为我觉得写 VueJS 代码的感觉最接近写 Python &/blockquote&&p&着重提一下单文件组件:&/p&&p&&figure&&img src=&https://pic4.zhimg.com/v2-ce179dcaa1a_b.jpg& data-rawwidth=&1246& data-rawheight=&1370& class=&origin_image zh-lightbox-thumb& width=&1246& data-original=&https://pic4.zhimg.com/v2-ce179dcaa1a_r.jpg&&&/figure&特别清晰,一个文件包含且仅包含三块&/p&&ol&&li&&template&&/template & 前端渲染的模板&/li&&li&专为此模板写渲染逻辑的 &script&&/script&&/li&&li&专为此模板写样式的 &style&&/style&&/li&&/ol&&p&这样可以达到什么效果呢?一个文件一个组件,每个组件有它自己的逻辑与样式,你不用关心什么 local 什么 global ,CSS样式加载先后、覆盖问题,因为它是『闭包』的,而且『自给自足』,不知道这样说好不好理解&/p&&p&当然组件之间也是可以通信的,举个例子,我有一个组件叫 ListULB ,使用表格展示了我拥有的所有 ULB (负载均衡),ListULB 做了一件事,从 API 获取 ULB 对象列表并 for 循环展现出来, ListULB 可以放到某个页面里,可以放到弹框里,放到模态框里,任何地方都可以,因为这个组件对外交互的只有API&/p&&p&如果我现在要写一个组件叫 AddVServer ,功能是可以为任意一个 ULB 对象添加VServer,我的写法是将在 AddVServer 组件创建的时候,将 ULB 对象传给 AddVServer 组件,这样AddVServer 组件拿到这个对象,就可以直接根据对象的ID等,创建出当前行的ULB的VServer了,伪代码如下:&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&ListULB&
for **ulb_object** in ulbs_list:
{{ ulb_object.name }}
{{ ulb_object.id }}
&AddVServer :current_ulb='**ulb_object**'&&/AddVServer&
&/ListULB&
&/code&&/pre&&/div&&p&注意双星号包着的对象,在 ListULB 组件里面是每行的ULB,传给AddServer组件之后,变成了 current_ulb 对象,拿到id为 current_ulb.id 尽情的为它创建 VServer 吧&/p&&p&如果我要为指定 VServer 创建 RServer 呢,一样的&/p&&blockquote&看出来了吧,进行开发之前,前端组件的结构与数据的结构对应起来可以省好多时间,数据驱动前端组件,棒吗?&/blockquote&&p&谁不喜欢优雅的代码呢, 『Data drive everything』 多么的省脑细胞&/p&&p&以上就是我选择Python与VueJS的原因&/p&&br&&br&&h2&Django与VueJS是如何结合起来?&/h2&&ul&&li&首先我选择了VueJS的前端渲染,自然放弃了Django的后端模板引擎渲染&/li&&li&然后业务逻辑放到了前端,放弃了Django的View(其实也就是前后端分离必要的条件)&/li&&li&保留了Django的 &u&C&/u&ontroller (URLconf) 来实现前端路由的父级路由,可以达到不同页面使用不同的前端框架, 页面内部使用各自独有的前端路由的效果,万一老大给你配了前端呢,万一前端只想写 ReactJS 呢&/li&&li&保留了Django的 Model ,前面说了Django的ORM太好用了,而且可以配合Django Admin&/li&&/ul&&p&所以综合来说就是:&/p&&blockquote&M(Django) + C(Django) + MVVM (VueJS) = &i&M + MVVM + C = MMVVMC&/i&&/blockquote&&br&&p&(为了容易理解,并没有使用Django自称的MTV模式理解,感兴趣看看我画的图)&/p&&figure&&img src=&https://pic3.zhimg.com/v2-d2a826bf7ef379eea16a6ac56971ce34_b.jpg& data-rawwidth=&3012& data-rawheight=&2104& class=&origin_image zh-lightbox-thumb& width=&3012& data-original=&https://pic3.zhimg.com/v2-d2a826bf7ef379eea16a6ac56971ce34_r.jpg&&&/figure&&br&&p&总结:作为以改变世界为己任的 DevOps ,MVC框架后端渲染的柔弱表现力与繁杂的交互已经不能满足我们了,.....省略1000子.....,所以我选择这样构建项目,嗯...&/p&&br&&p&好吧,也该开始了&/p&&p&代码块中的修改都会用爽星号括起来,比如: **changed**&/p&&p&本文为了精简篇幅,默认您已经安装了必要的 命令行界面(CLI),比如 vue-cli等&/p&&br&&br&&h2&1. 创建Django项目&/h2&&figure&&img src=&https://pic2.zhimg.com/v2-0b8ed26d48a1ad0b412cec59aeb3db03_b.jpg& data-rawwidth=&500& data-rawheight=&228& class=&origin_image zh-lightbox-thumb& width=&500& data-original=&https://pic2.zhimg.com/v2-0b8ed26d48a1ad0b412cec59aeb3db03_r.jpg&&&/figure&&p&&i&命令:&/i&&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&django-admin startproject ulb_manager
&/code&&/pre&&/div&&p&&i&结构:&/i&&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.
├── manage.py
└── ulb_manager
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
&/code&&/pre&&/div&&br&&h2&2. 进入项目根目录,创建一个 app 作为项目后端&/h2&&p&&i&命令:&/i&&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&cd ulb_manager
python manage.py startapp backend
&/code&&/pre&&/div&&p&即:app 名叫做 backend &/p&&p&&i&结构:&/i&&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.
├── backend
├── __init__.py
├── admin.py
├── migrations
└── __init__.py
├── models.py
├── tests.py
└── views.py
├── manage.py
└── ulb_manager
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
&/code&&/pre&&/div&&br&&h2&3. 使用vue-cli创建一个vuejs项目作为项目前端&/h2&&figure&&img src=&https://pic1.zhimg.com/v2-df081aadcb6c5b35b7aea8_b.jpg& data-rawwidth=&400& data-rawheight=&400& class=&content_image& width=&400&&&/figure&&br&&p&&i&命令:&/i&&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&vue-init webpack frontend
&/code&&/pre&&/div&&p&即:项目名叫 frontend &/p&&p&&i&结构:&/i&&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&.
├── backend
├── __init__.py
├── admin.py
├── migrations
└── __init__.py
├── models.py
├── tests.py
└── views.py
├── frontend
├── README.md
├── build
└── ....
├── config
├── dev.env.js
├── index.js
├── prod.env.js
└── test.env.js
├── index.html
├── package.json
├── src
├── App.vue
├── assets
└── logo.png
├── components
└── Hello.vue
└── main.js
├── static
└── test
└── ...
├── manage.py
└── ulb_manager
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
&/code&&/pre&&/div&&br&&p&&i&结构总结:&/i&&/p&可以看到项目根目录有两个新文件夹,一个叫 backend ,一个叫 frontend,分别是:&ul&&li&backend
Django的一个app&/li&&li&frontend
Vuejs项目&/li&&/ul&&br&&br&&h2&4. 接下来我们使用 webpack 打包Vusjs项目&/h2&&figure&&img src=&https://pic3.zhimg.com/v2-c069d74a397a933cb6055b_b.jpg& data-rawwidth=&2598& data-rawheight=&1299& class=&origin_image zh-lightbox-thumb& width=&2598& data-original=&https://pic3.zhimg.com/v2-c069d74a397a933cb6055b_r.jpg&&&/figure&&p&&i&命令:&/i&&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&cd frontend
npm install
npm run build
&/code&&/pre&&/div&&p&&i&结构:&/i&&/p&&i&我引入了一些包,比如element-ui等,你的static里面的内容会不同,没关系 index.html 和 static 文件夹相同就够了&/i&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&dist
├── index.html
└── static
├── css
├── app.42b821a6fde2af5bf3b5d2.css
└── app.42b821a6fde2af5bf3b5d2.css.map
├── fonts
├── element-icons.a61be9c.eot
└── element-icons.b02bdc1.ttf
├── img
└── element-icons.09162bc.svg
├── 0.ffd70f7ba6.js
├── vendor.a7c622c4cb5b.js
└── vendor.a7c622c4cb5b.js.map
&/code&&/pre&&/div&&p&构建完成会生成一个 文件夹名字叫dist,里面有一个 index.html 和一个 文件夹static ,&/p&&br&&br&&h2&5. 使用Django的通用视图 &u&TemplateView&/u&&/h2&&p&找到项目根 urls.py (即ulb_manager/urls.py),使用通用视图创建最简单的模板控制器,访问 『/』时直接返回 index.html&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&urlpatterns = [
url(r'^admin/', admin.site.urls),
**url(r'^$', TemplateView.as_view(template_name=&index.html&)),**
url(r'^api/', include('backend.urls', namespace='api'))
&/code&&/pre&&/div&&br&&h2&6. 配置Django项目的模板搜索路径&/h2&&p&上一步使用了Django的模板系统,所以需要配置一下模板使Django知道从哪里找到index.html&/p&&p&打开 settings.py (ulb_manager/settings.py),找到TEMPLATES配置项,修改如下:&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&TEMPLATES = [
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# 'DIRS': [],
**'DIRS': ['frontend/dist']**,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
&/code&&/pre&&/div&&p&注意这里的 frontend 是VueJS项目目录,dist则是运行 npm run build 构建出的index.html与静态文件夹 static
的父级目录&/p&这时启动Django项目,访问 / 则可以访问index.html,但是还有问题,静态文件都是404错误,下一步我们解决这个问题&br&&br&&h2&7. 配置静态文件搜索路径&/h2&&p&打开 settings.py (ulb_manager/settings.py),找到 STATICFILES_DIRS 配置项,配置如下:&br&&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# Add for vuejs
STATICFILES_DIRS = [
os.path.join(BASE_DIR, &frontend/dist/static&),
&/code&&/pre&&/div&&p&这样Django不仅可以将/ulb 映射到index.html,而且还可以顺利找到静态文件&br&&/p&&p&此时访问 /ulb 我们可以看到使用Django作为后端的VueJS helloworld&/p&&p&ALL DONE.&/p&&br&&br&&h2&8. 开发环境&/h2&&p&因为我们使用了Django作为后端,每次修改了前端之后都要重新构建(你可以理解为不编译不能运行)&/p&&p&除了使用Django作为后端,我们还可以在dist目录下面运行以下命令来看效果:&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&hs(即: http server)
&/code&&/pre&&/div&&p&&figure&&img src=&https://pic1.zhimg.com/v2-63bb75e8e032b4af38ffa6_b.jpg& data-rawwidth=&536& data-rawheight=&308& class=&origin_image zh-lightbox-thumb& width=&536& data-original=&https://pic1.zhimg.com/v2-63bb75e8e032b4af38ffa6_r.jpg&&&/figure&但是问题依然没有解决,我想过检测文件变化来自动构建,但是构建是秒级的,太慢了,所以我直接使用VueJS的开发环境来调试&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&npm run dev
&/code&&/pre&&/div&&p&&figure&&img src=&https://pic4.zhimg.com/v2-9eb17d07a276d968e24dd13d39b6da73_b.jpg& data-rawwidth=&586& data-rawheight=&182& class=&origin_image zh-lightbox-thumb& width=&586& data-original=&https://pic4.zhimg.com/v2-9eb17d07a276d968e24dd13d39b6da73_r.jpg&&&/figure&毫秒,但是有个新问题,使用VueJS的开发环境脱离了Django环境,访问Django写的API,出现了跨域问题,有两种方法解决,一种是在VueJS层上做转发(proxyTable),另一种是在Django层注入header,这里我使用后者,用Django的第三方包 django-cors-headers 来解决跨域问题&/p&&p&安装&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&pip install django-cors-headers
&/code&&/pre&&/div&&p&配置(两步)&/p&&p&1. settings.py 修改&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
**'corsheaders.middleware.CorsMiddleware',**
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
&/code&&/pre&&/div&&p&这里要注意中间件加载顺序,列表是有序的哦&/p&&p&2. settings.py 添加&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&CORS_ORIGIN_ALLOW_ALL = True
&/code&&/pre&&/div&&p&至此,我的开发环境就搭建完成了&/p&&br&&br&&h2&9. 生产环境部署(部署到 UCloud )&/h2&&p&接下来我们尝试将项目部署到UCloud云主机上:&br&&br&&/p&&p&9.1 创建主机&/p&&ol&&li&注册 &a href=&https://link.zhihu.com/?target=https%3A//ucloud.cn/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&UCloud - 专业云计算服务商&/a&&/li&&li&点击左侧的 云主机,然后点击 创建主机&/li&&li&右侧选择 付费方式,点击 立即购买&/li&&li&在支付确认页面,点击 确认支付&/li&&/ol&&p&购买成功后回到主机管理列表,如下所示:&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-5d91cf1a3de229bffc8b4b_b.jpg& data-rawwidth=&2456& data-rawheight=&402& class=&origin_image zh-lightbox-thumb& width=&2456& data-original=&https://pic1.zhimg.com/v2-5d91cf1a3de229bffc8b4b_r.jpg&&&/figure&&blockquote&这里注意记住你的外网IP,下面的ip替换成你的&br&&/blockquote&&br&&p&9.2 环境搭建与部署&/p&&p&登录主机,用你刚填写的密码:&/p&&blockquote&ssh root@120.132.**.75&/blockquote&&p&CentOS 系统可以使用 yum 安装必要的包&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 如果你使用git来托管代码的话
yum install git
# 如果你要在服务器上构建前端
yum install nodejs
yum install npm
yum install nginx
&/code&&/pre&&/div&&blockquote&我们使用 uwsgi 来处理 Django 请求,使用 nginx 处理 static 文件(即之前 build 之后 dist 里面的static,这里默认前端已经打包好了,如果在服务端打包前端需要安装nodejs,npm等)&/blockquote&&p&安装uWsgi&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&yum install uwsgi
pip install uwsgi
&/code&&/pre&&/div&&p&我们使用配置文件启动uwsgi,比较清楚&/p&&p&uwsgi配置文件:&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&[uwsgi]
socket = 127.0.0.1:9292
stats = 127.0.0.1:9293
workers = 4
# 项目根目录
chdir = /opt/inner_ulb_manager
touch-reload = /opt/inner_ulb_manager
py-auto-reload = 1
# 在项目跟目录和项目同名的文件夹里面的一个文件
module= inner_ulb_manager.wsgi
pidfile = /var/run/inner_ulb_manager.pid
daemonize = /var/log/inner_ulb_manager.log
&/code&&/pre&&/div&&p&nginx 配置文件:&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&server {
listen 8888;
server_name 120.132.**.75;
root /opt/inner_ulb_
access_log /var/log/nginx/access_narwhals.
error_log /var/log/nginx/error_narwhals.
location / {
uwsgi_pass 127.0.0.1:9292;
include /etc/nginx/uwsgi_
location /static/ {
/opt/inner_ulb_manager/;
location ^~ /admin/ {
uwsgi_pass 127.0.0.1:9292;
include /etc/nginx/uwsgi_
&/code&&/pre&&/div&&p&/opt/inner_ulb_manager/static 即为静态文件目录,那么现在我们静态文件还在 frontend/dist 怎么办,不怕,Django给我们提供了命令:&/p&&p&先去settings里面配置:&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&STATIC_ROOT = os.path.join(BASE_DIR, &static&)
&/code&&/pre&&/div&&p&然后在存在manage.py的目录,即项目跟目录执行:&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&python manage.py collectstatic
&/code&&/pre&&/div&&p&这样frontend/dist/static里面的东西就到了项目根目录的static文件夹里面了&/p&&p&那么为什么不直接手动把构建好的dist/static拷过来呢,因为开始提过Django自带的App:admin 也有一些静态文件(css,js等),它会一并collect过来,毕竟nginx只认项目跟目录的静态文件,它不知道django把它自己的需求文件放到哪了&/p&&p&开头说过Django配置灵活,那么我们专门为Django创建一个生产环境的配置 prod.py&br&&/p&&p&prod.py 与 默认 settings.py 同目录&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 导入公共配置
from .settings import *
# 生产环境关闭DEBUG模式
DEBUG = False
# 生产环境开启跨域
CORS_ORIGIN_ALLOW_ALL = False
# 特别说明,下面这个不需要,因为前端是VueJS构建的,它默认使用static作为静态文件入口,我们nginx配置static为入口即可,保持一致,没Django什么事
STATIC_URL = '/static/'
&/code&&/pre&&/div&&br&如何使用这个配置呢,进入 wisg.py 即uwsgi配置里面的module配置修改为:&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault(&DJANGO_SETTINGS_MODULE&, &**inner_ulb_manager.prod**&)
application = get_wsgi_application()
&/code&&/pre&&/div&&p&启动uwsgi&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&uwsgi --ini inner_ulb_manager.ini
&/code&&/pre&&/div&&br&&p&启动ngingx&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&service nginx start
&/code&&/pre&&/div&&p&至此,部署就完成了&/p&&br&&br&&h2&10. 效果图&/h2&&p&List 组件:&/p&&figure&&img src=&https://pic4.zhimg.com/v2-9ba179e9b3_b.jpg& data-rawwidth=&2872& data-rawheight=&1626& class=&origin_image zh-lightbox-thumb& width=&2872& data-original=&https://pic4.zhimg.com/v2-9ba179e9b3_r.jpg&&&/figure&&blockquote&&i&传单个 ULB 对象给 Detail 组件使用即可&/i&&/blockquote&&p&Detail 组件:&/p&&figure&&img src=&https://pic2.zhimg.com/v2-705538ffd2dae_b.jpg& data-rawwidth=&2854& data-rawheight=&724& class=&origin_image zh-lightbox-thumb& width=&2854& data-original=&https://pic2.zhimg.com/v2-705538ffd2dae_r.jpg&&&/figure&&blockquote&&i&当然里面还实现了前面提到的 ULB 的 VServer 创建,VServer 的 RServer 的创建等。&/i&&/blockquote&————————&br&&br&本文由『&b&UCloud平台产品研发团队&/b&』提供。&br&&br&项目源码文件戳下面链接查看,大家可以马上拿源码上手试起来,操作过程中遇到问题也可直接在github上留言:)&a href=&https://link.zhihu.com/?target=https%3A//github.com/tmpbook/django-with-vuejs& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/tmpbook/djan&/span&&span class=&invisible&&go-with-vuejs&/span&&span class=&ellipsis&&&/span&&/a&&br&&br&&p&现在注册使用UCloud,还免费试用 及 首充返现优惠,最高可返3000元代金券!活动传送门:&a href=&https://link.zhihu.com/?target=https%3A//www.ucloud.cn/site/active/gift.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&用UCloud!3000元限量版礼盒等你来拆!&/a&&/p&&p&另,欢迎添加UCloud运营小妹个人微信号:Surdur,陪聊很专业:)&/p&&figure&&img src=&https://pic3.zhimg.com/v2-d9f126c9dda34b630523e_b.jpg& data-rawwidth=&1000& data-rawheight=&350& class=&origin_image zh-lightbox-thumb& width=&1000& data-original=&https://pic3.zhimg.com/v2-d9f126c9dda34b630523e_r.jpg&&&/figure&&br&&blockquote&&p&&b&关于作者:&/b&&/p&星辰(&a href=&https://www.zhihu.com/people/tmpbook/activities& class=&internal&&@星辰&/a&), UCloud平台产品研发工程师,DevOps一枚。你也可以去他的知乎专栏 &a href=&https://zhuanlan.zhihu.com/heart-devops& class=&internal&&《随心DevOps》&/a& 上逛逛,干货满满,带你更优雅的改变世界。&/blockquote&&br&&h2&相关阅读推荐:&/h2&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&机器学习进阶笔记之八 | TensorFlow与中文手写汉字识别&/a&&br&&br&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&机器学习进阶笔记之七 | MXnet初体验&/a&&br&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&机器学习进阶笔记之六 | 深入理解Fast Neural Style&/a&&br&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&机器学习进阶笔记之五 | 深入理解VGG\Residual Network&/a&&br&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&机器学习进阶笔记之四 | 深入理解GoogLeNet&/a&&br&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&机器学习进阶笔记之三 | 深入理解Alexnet &/a&&br&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&机器学习进阶笔记之二 | 深入理解Neural Style&/a&&br&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&机器学习进阶笔记之一 | TensorFlow安装与入门&/a&&br&&br&&p&「UCloud机构号」将独家分享云计算领域的技术洞见、行业资讯以及一切你想知道的相关讯息。&/p&&p&欢迎提问&求关注 o(*////▽////*)q~&/p&&p&以上。&/p&
引言 的新年第一课,祝大家新的一年好好学习,天天向上:) 本篇将手把手教你如何快速而优雅的构建前后端分离的项目,想直接上手请往后翻! 目录:我为什么要选择Django与VueJS?Django和VueJS是如何结合起来的?实操创建 Django 项目创建 Dja…
&p&&b&Awesome Python中文版来啦!&/b&&br&&/p&&p&本文由 &a href=&//link.zhihu.com/?target=http%3A//python.jobbole.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&伯乐在线&/a& - &a href=&//link.zhihu.com/?target=http%3A//www.jobbole.com/members/hanxiaomax& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&艾凌风&/a& 翻译,&a href=&//link.zhihu.com/?target=http%3A//www.jobbole.com/members/namco1992& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Namco&/a& 校稿。未经许可,禁止转载!&br&英文出处:&a href=&//link.zhihu.com/?target=https%3A//github.com/vinta/awesome-python& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&github.com&/a&。欢迎加入&a href=&//link.zhihu.com/?target=http%3A//group.jobbole.com/category/feedback/trans-team/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&翻译组&/a&。&br&&/p&&br&&br&原文链接:&a href=&//link.zhihu.com/?target=http%3A//python.jobbole.com/84464/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Python 资源大全&/a&&br&&br&1200+收藏,600+赞,别只顾着自己私藏呀朋友们&br&&p&----------------&/p&&p&这又是一个 Awesome XXX 系列的资源整理,由 vinta 发起和维护。内容包括:Web框架、网络爬虫、网络内容提取、模板引擎、数据库、数据可视化、图片处理、文本处理、自然语言处理、机器学习、日志、代码分析等。&/p&&p&伯乐在线已在 GitHub 上发起「Python 资源大全中文版」的整理。欢迎扩散、欢迎加入。&/p&&p&&a href=&//link.zhihu.com/?target=https%3A//github.com/jobbole/awesome-python-cn& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&GitHub - jobbole/awesome-python-cn: Python资源大全中文版&/a&&/p&&b&环境管理&/b&&p&管理 Python 版本和环境的工具&/p&&ul&&li&&a href=&//link.zhihu.com/?target=https%3A//github.com/qw3rtman/p& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&p&/a& – 非常简单的交互式 python 版本管理工具。&/li&&li&&a href=&//link.zhihu.com/?target=https%3A//github.com/yyuu/pyenv& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&pyenv&/a& – 简单的 Python 版本管理工具。&/li&&li&&a href=&//link.zhihu.com/?target=https%3A//github.com/sashahart/vex& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Vex&/a& – 可以在虚拟环境中执行命令。&/li&&li&&a href=&//link.zhihu.com/?target=https%3A//pypi.python.org/pypi/virtualenv& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&virtualenv&/a& – 创建独立 Python 环境的工具。&/li&&li&&a href=&//link.zhihu.com/?target=https%3A//pypi.python.org/pypi/virtualenvwrapper& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&virtualenvwrapper&/a&- virtualenv 的一组扩展。&/li&&/ul&&b&包管理&/b&&p&管理包和依赖的工具。&/p&&ul&&li&&a href=&//link.zhihu.com/?target=https%3A//pip.pypa.io/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&pip&/a& – Python 包和依赖关系管理工具。&/li&&li&&a href=&//link.zhihu.com/?target=https%3A//github.com/nvie/pip-tools& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&pip-tools&/a& – 保证 Python 包依赖关系更新的一组工具。&/li&&li&&a href=&//link.zhihu.com/?target=https%3A//github.com/conda/conda/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&conda&/a& – 跨平台,Python 二进制包管理工具。&/li&&li&&a href=&//link.zhihu.com/?target=http%3A//clarete.li/curdling/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Curd}

我要回帖

更多关于 www.9cmv.com 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信