近来写复旦二手平台的时刻最先尝试用一向推重了良久的组件化。经由一番挑选以后挑选了 webpack + angular 的组合。所以在这里分享一下细致的实践流程。
Webpack
Webpack是如今比较盛行的前端打包东西,它同时支撑AMD、CMD两种模块写法,也原生支撑npm或许bower装置的模块。它还能给css、scss、less、coffeescript、es6、图片、html以及诸如jade、ejs的模板打包。
所以有什么卵用呢?
简朴地说就是,
1、本来你须要在<script>
中引入angular或许其他的npm模块(有些npm模块以至没有供应能够直接在浏览器端援用的js文件),如今只须要:
npm install angular
然后在app.js中:
angular = require('angular');
var app = angular.module('myApp',[]);
然后实行
webpack app.js bundle.js
webpack会自动剖析依靠,然后编译,如许bundle.js
就是你想要的东西了。
2、组件化的时刻你要在页面中引入一大堆东西,比方如许:
<!--index.html-->
<script type="text/javascript" src="header.js">
<script type="text/javascript" src="tab.js">
<script type="text/javascript" src="waterfoo.js">
<link rel="stylesheet" type="text/css" href="header.css">
<link rel="stylesheet" type="text/css" href="tab.css">
<link rel="stylesheet" type="text/css" href="waterfoo.css">
固然你能够不会用云云傻的体式格局引入组件,但假如用了webpack以后只须要如许:
//index-bundle.js
require('header.js');
require('header.scss');
require('tab.js');
require('tab.scss');
require('waterfoo.js');
require('waterfoo.scss');
然后在index.html中引入打包好的js即可(没错连scss都给你打包好了/w\ 它以至还能把图片打包成base64,然后替代一切url):
<!--index.html-->
<script type="text/javascript" src="bundle.js">
上面只是最基本的用法,所以有些人能够要吐槽这不是browserify也能干么/w\ 能够看看这篇文章[《用webpack来庖代browserify》
](http://segmentfault.com/a/1190000002490637),以及webpack另有许多酷炫的功用这里就不再赘述。
项目实践流程
回到正题吧,复旦二手平台这个项目更像是多页面的网站而不是单页面的web运用,所以我决议尝试用node去写一个衬着层(个人感觉Koajs如今还不太成熟,所以选用了Express4.0),如许背景写JAVA的同砚就只须要给我供应数据API就好了,把数据库接口化。
衬着引擎用的是jade,而angular的角色更像是一个页面的“掌握器”,掌握由jade天生的页面,而不是去自行加载html自行衬着(说白了就是摒弃了用angular衬着页面)。
Webpack和Angular的连系
Angular自带了Module以及Directive机制,但Angular1.x版本下,我以为这些机制不太适合做这类多页面网站的组件化,而且也违犯了选用jade衬着的初志。
Angular本身有本身奇特的依靠注入以及模块声明体式格局,看起来好像和Webpack是方枘圆凿的,但事实上他们完全能够融会。只须要多几行代码:
主文件app.js也许长如许:
var angular = require('angular');
var starkAPP = angular.module('starkAPP', [
]);
module.exports = starkAPP;
注意到我们在这里把starkAPP作为模块的接口暴露出去,然后我们就能够如许写controller:
//someController.js
var starkAPP = require('./app.js');
starkAPP.controller('someController', ['$scope', function($scope) {
//...
}])
运转一下webpack someController.js bundle.js
即天生了一个能够运用的bundle.js。
固然假如你有一堆controller、directive、service,最好用个main.js
悉数声明一下依靠:
//main.js
require('./Controller1');
require('./Controller2');
require('./Controller3');
require('./Service');
require('./Directive');
目次构造设计
这里我只放了浏览器端的文件构造,全部的项目构造能够看这里
|package.json 寄存npm相干的设置
|gulpfile.js gulp的设置文件
|webpack.config.js 寄存webpack相干的设置
|build 寄存构建终了的资本文件
|node_modules 不诠释了= =
|src 源代码
└── components 组件
├── angular angular组件,比方种种directive、service
├── base 须要全站引入的组件,比方reset.css
└── header 头部组件
├── header.jade
├── header.scss
└── header.js
└── pages 页面定义文件
└── index 首页设置文件
├── index.js
└── index.scss
└── template 供应给node衬着的jade模板
└── index.jade 首页模板
看文件构造相对是云里雾里的,下面细致申明:
1、起首这是首页的模板index.jade
html(ng-app="starkAPP")
head
link(rel='stylesheet',href='/static/css/index.css')
script(type='text/javascript',src='/static/js/index.bundle.js')
body(ng-view)
include ../components/header/header.jade
注意到我们引入了header的jade,以及两个文件index.css
和index.bundle.js
2、index.css
是啥?
它是pages/index/
内里的index.scss
编译成的:
// pages/index/index.scss
@import '../../components/header/header';
@import '../../components/base/base';
注意到我们在这里引入了header.scss
3、index.bundle.js
是啥?
它是pages/index/
内里的index.js
经由webpack打包成的东西
// pages/index/index/js
require('../../components/angular/app.js');
require('../../components/header/header.js');
我们在这里引入了angular以及header.js
总之,pages下面放的就是各个页面的组件依靠文件
比方我的首页index依靠了一个组件header,那末我须要在index.js
和index.scss
中声明我依靠了header.js
以及header.scss
其有用webpack打包的话,只须要一个定义文件就能够同时打包js和scss,但我还不太肯定webpack打包scss这类要领是不是成熟。
项目构建
自动构建东西我挑选了gulp百口桶,简朴地说就是读取src/pages/[page-name]
下面一切的js、scss文件,把他们编译到对应的build/[page-name]
下面,而且监听文件变化以便热替代。
这是我的gulpfile.js
:
var gulp = require('gulp');
var sass = require('gulp-sass'),
autoprefixer = require('gulp-autoprefixer'),
minifycss = require('gulp-minify-css'),
uglify = require('gulp-uglify'),
clean = require('gulp-clean'),
webpack = require('gulp-webpack');
var webpackConfig = require('./webpack.config');
gulp.task('default', ['clean', 'watch', 'sass:watch', 'sass', 'webpack']);
gulp.task('sass:watch', function() {
gulp.watch('src/pages/*/*.scss', ['sass']);
gulp.watch('src/components/*/*.scss', ['sass']);
});
gulp.task('sass', function() {
gulp.src(['src/pages/**/*.scss'])
.pipe(sass.sync().on('error', sass.logError))
.pipe(minifycss())
.pipe(gulp.dest('build/pages'));
});
gulp.task('clean', function() {
return gulp.src(['build/pages'], {
read: false
})
.pipe(clean());
});
gulp.task("webpack", function() {
return gulp
.src('./')
.pipe(webpack(webpackConfig))
//.pipe(uglify())
.pipe(gulp.dest('./build/pages'));
});
gulp.task('watch', function() {
gulp.watch('src/components/*/*.js', ['webpack']);
gulp.watch('src/pages/*/*.js', ['webpack']);
});
以及简化后的webpack.config.js
:
module.exports = {
entry: {
'index/index': './src/pages/index/index.js'
},
output: {
filename: '[name].bundle.js'
}
};
怎样写一个组件?
比方如今我们要写一个waterfoo(瀑布流)组件
起首我们在src/components/
下面新建一个文件夹waterfoo
,然后竖立
waterfoo.jade
waterfoo.scss
waterfoo.js
离别对应waterfoo组件的模板、款式、以及行动,固然waterfoo组件完全能够依靠其他更低层级组件,只须要在响应的文件中声明依靠即可。
怎样在页面中到场组件?
比方如今我们要把waterfoo(瀑布流)组件加到首页index中
起首在src/template/index.jade
中引入模板:
include ../components/waterfoo/waterfoo.jade
然后在src/pages/index/
下面的index.js
、index.scss
设置依靠:
//index.js
require('../../components/waterfoo/waterfoo');
//index.scss
@import '../../components/waterfoo/waterfoo';
有更文雅更傻瓜的要领吗?
固然有,将来的希冀是用webpack把js和scss一同打包,而且把template
和pages
文件夹兼并(细致设置express衬着途径的要领我还在探究),也许就是如许的结果:
src/pages/index/
下面放着首页的设置文件:
index.jade
index-config.js
index.scss (一些非组件的款式)
index.jade是模板
html(ng-app="starkAPP")
head
script(type='text/javascript',src='/static/js/index.bundle.js')
body(ng-view)
include ../components/header/header.jade
index-config.js声明依靠的组件
require('../../components/angular/app.js');
require('../../components/header/header.js');
require('../../components/header/header.scss');
require('../../components/waterfoo/waterfoo.js');
require('../../components/waterfoo/waterfoo.scss');
require('./index.scss');
——-
末了
这个项目的源码在Github · starkwang/FDSHM,FDSHM是Fudan Secondhand Market的缩写/w\,如今还在慢慢地写组件中,争夺这学期上线吧……(缺人啊QAQ)