前端快速開發模版

原文地址:前端快速開發模版javascript

以前一直在開發移動端的單頁面應用,而移動web對性能和效果要求是比較苛刻的,因此用的都是輕量級的框架體系。基本上是Zepto加本身開發的單頁面框架,再加上若干簡單的庫。這樣前端要加載的文件很小,修改起來也很是方便,同時這樣的輕量級的體系使用gulp進行自動化管理也是很是合適的。css

自從開發react項目後,對它的工程化和開發模式也是開了眼界,標準的框架體系就是重量級的react+redux+webpack。開發大型項目和後臺管理系統用react,vue確實是不錯的。可是開發一些小項目,好比前端h5之類的又有殺雞用牛刀的感受。html

因而借鑑webpack工程化思想動手寫了個前端快速開發模版,用於開發快速簡潔的項目,好比以前的單頁面應用。而這個項目模版就是相似前端開發的腳手架了,基本的思路就是自動化和前端編譯 ,主要達到如下目的:前端

  1. 使用less預編譯css,使用autoprefixer進行樣式兼容
  2. js代碼用babel編譯,所以可基於es6,es7編寫代碼
  3. 類庫文件使用npm包,js文件使用browserify組織和打包,再也不使用sea,require之類的加載器
  4. html代碼使用swig模版引擎進行組織和預編譯
  5. 靜態資源版本使用rev管理,當css或js文件內容有變化,打包時自動更新版本
  6. 前端開發基礎樣式,框架的整合。

工具鏈

  • 構建工具gulp
  • 編譯打包工具browserify
  • 代碼編譯babel
  • css兼容autoprefixer
  • css預編譯less
  • html代碼預編譯模版swig
  • 前端代碼版本更新rev

公共類庫

  • jQuery
  • Zepto
  • 本身開發的簡潔單頁面框架app.js
  • 圖標fontello
  • 字體reboto
  • 基礎樣式base.css

文件目錄結構

  • css: css文件
  • less: less文件
  • js: js文件
  • dist: 打包生成的項目文件
  • layout: html母板
  • lib: 公共類庫
  • template: html頁面

項目自動化

沒有使用重量級的webpack,而是使用輕量級的gulp和browserifyvue

公共類庫

公共類庫的文件,主要有基礎樣式base.css,圖標樣式reboto,字體樣式fontello,單頁面框架app,直接拷貝到dist文件就ok。其餘npm包跟nodejs項目同樣在node_modules中,不須要處理。java

//複製公共庫目錄下的全部內容
gulp.task('copy',function(){
  return gulp.src('./lib/**')
    .pipe(gulp.dest('./dist/lib/'));
});

css文件

首先將less文件轉爲css,用autoprefixer添加兼容性前綴,合併壓縮,放到dist目錄,最後用rev插件生成版本信息,這個後面用於替換更新連接用。node

//編譯css,添加兼容後綴,壓縮
gulp.task('css', function() {
  return gulp.src('./less/*.less')
    .pipe(less())
  // .pipe(concatCss("index.css"))
    .pipe(postcss([ autoprefixer({
      "browsers": ["last 2 version", "> 0.5%", "ie 6-8","Firefox < 20"]
      // "browsers": ["last 2 version", "> 0.1%"]
    })
                  ]))
    .pipe(cleanCSS())
  // .pipe(rename({suffix: '.min'}))
  // .pipe(gulp.dest('./dist/css'));
    .pipe(rev())
    .pipe(gulp.dest('./dist/css'))
    .pipe(rev.manifest())
    .pipe(gulp.dest('./rev/css'));

});

js文件

我這裏有兩個入口文件,能夠隨時將新入口文件添加到scripts數組中,這裏作的就是使用babel轉換代碼,而後將外部文件,npm包打包進來,生成sourcemap,輸出到dist文件夾,最後同樣用rev插件生成版本信息。react

var scripts=['app','index'];
scripts.map(name=>{
  gulp.task(name,function(){
    return  browserify({
      entries:'./js/'+name+'.js',  //entries file name
      debug:true // set true so the bundle file can generate sourcemap 
    })
      .transform(babelify,{ 
      plugins: ["transform-runtime"],
      presets: [
        'es2015',  //convert to es5
        'stage-0'  //es7
      ]
    })
      .bundle()  //merge
      .pipe(source(name+'.js'))
      .pipe(buffer())
    // .pipe(uglify())
      .pipe(sourcemaps.init({loadMaps: true})) //External sourcemap file
      .pipe(sourcemaps.write('./'))
      .pipe(rev())
      .pipe(gulp.dest('./dist/js/'))
      .pipe(rev.manifest(name+'.json'))
      .pipe(gulp.dest('./rev/js/'));
  });
});

html文件

html編譯我使用的是模版引擎是swig,這裏用的是gulp-swig插件,固然也能夠用ejs或jade的引擎。但我我的比較習慣用swig,由於它更靈活,支持各類文件格式,能夠直接使用html文件,也支持ejs不支持的layout等。gulp-swig插件的使用也很是簡單。webpack

//swig編譯輸出html
gulp.task('html', function() {
  return gulp.src('./template/*.html')
    .pipe(swig({
    defaults: {cache: false }
  }))
    .pipe(gulp.dest('./'))
});

文件版本控制

以前編譯css和js的時候已經調用rev生成了記錄了版本信息的json文件,若是內容有變化它會生成新的md5文件名。這裏就是用rev-collector替換html文件中除md5部分外相同文件名的連接,這樣就就實現了版本更新功能,用這個插件能夠更新css,js,圖片等的版本。git

//更新css和js版本,同時替換html中的連接標籤
gulp.task('rev', scripts.concat(["css","html"]),function () {
  return gulp.src(['./rev/**/*.json', './*.html'])//add md5 suffix to js and css file, replace the link of html as well 
    .pipe( revCollector({
    replaceReved: true,
    dirReplacements: {
      '/css': '/css',
      '/js': '/js'
    }
  }))
    .pipe( gulp.dest('./dist') );
});

html裏面替換後的連接格式以下

<link rel="stylesheet" href="./css/app-d333f590b0.css">
<script src="./js/app-62bad8e549.js"></script>

項目模版

項目自動化配置完後,接着就是配置項目模版了,這裏分兩種類型的模版:1.移動端優先的單頁面;2.pc端優先的普通頁面。
swig標籤語法

  • extends 繼承父模板,必須在文件最前
  • block 定義一個塊,使之能夠被繼承的模板重寫,或者重寫父模板的同名塊
  • parent 將父模板中同名塊注入當前塊中
  • include 包含一個模板到當前位置

移動端單頁面模版

在layout文件夾新建移動端的單頁面模版app-layout.html,而後再創建子目錄partial,用於存放公共代碼塊。

咱們知道加載頁面時再去加載外部文件是須要耗費加載時間,而頁面直出能夠大大提升加載速度,同時預先加載部分樣式也能夠避免加載時的白屏問題。這也是咱們這裏將公共部分的js和css以代碼塊的形式嵌入到html文件中,達到頁面直出的效果。

swig支持將html文件嵌入,同時也能夠將css文件嵌入,我這裏就是把單頁面樣式文件app.css和基礎樣式文件app-base.css的內容直接輸出到style標籤中。主要的代碼塊有:

  • meta.html: 頭部meta標籤
  • header-script.html: 主要是動態設置fontsize大小的腳本
  • footer-script.html: 主要是頁面加載過程的動畫腳本

固然了圖標樣式,好看的字體文件,單頁面的css,基礎的樣式css都有, 同時母版還挖出了幾個block給繼承的頁面進行重寫,好比block title,block css,block js,內容block content。css塊和js塊既能夠寫外部連接也能夠直接寫代碼。 咱們能夠根據本身的需求進行修改和配置文件,具體內容看以下代碼。

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>{% block title %}{% endblock %}</title>
    {% include './partial/meta.html' %}
    <!-- 頁面內加載的頭部js -->
    {% include './partial/header-script.html' %}
    <!-- 頁面內加載的css -->
    <style>{% include '../lib/app/app.css' %}{% include '../lib/app-base.css' %}</style>
    <!-- 圖標 -->
    <link rel="stylesheet" href="./lib/fontello/fontello.css">
    <!-- 字體 -->
    <link rel="stylesheet" href="./lib/reboto/roboto.css">
    <!-- 項目css -->
    <link rel="stylesheet" href="./css/app.css">
    <!-- 外部css塊 -->
    {% block css %}{% endblock %}
  </head>
  <body>
    <div id="app" class="view-wrap"></div>
    <div id="loading" class="loading-wrap">
      <div class="loading">
        <div class="round"></div>
        <div class="txt">0%</div>
      </div>
    </div>
    <div id="freshing" class="fresh-wrap">
      <div class="loading">
        <div class="round"></div>
        <p class="txt">loading...</p>
      </div>
    </div>
    <!-- 內容填充塊 -->
    {% autoescape false %}
    {% block content %}{% endblock %}
    {% endautoescape %}
    <!-- 頁面內加載的尾部js -->
    {% include './partial/footer-script.html' %}
    <!-- 外部js塊 -->
    {% block js %}{% endblock %}
  </body>
</html>

PC端優先模版

接着就是創建PC端優先的模版layout.html,這個和單頁面模版類似,主要區別就是基礎樣式,同時不用嵌入移動端的代碼,頁面模版請看以下代碼:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>{% block title %}{% endblock %}</title>
    {% include './partial/meta.html' %}
    <link rel="stylesheet" href="./lib/fontello/fontello.css">
    <link rel="stylesheet" href="./lib/reboto/roboto.css">
    <style>{% include '../lib/base.css' %}</style>
    <link rel="stylesheet" href="./css/index.css">
    {% block css %}{% endblock %}
  </head>
  <body>
    {% autoescape false %}
    {% block content %}{% endblock %}
    {% endautoescape %}
    {% include './partial/copyright.html' %}
    {% block js %}{% endblock %}
  </body>
</html>

使用方式

項目模板完成了,我以創建單頁面項目爲例演示使用的步驟

  1. 首先從github clone模版到文件夾webapp-project,安裝相關npm包。

    git clone https://github.com/edwardzhong/project-template.git webapp-project
    npm install
  2. 在less文件夾內創建app.less,並編寫代碼

    @lightBlue:hsl(198, 73%, 53%);
    
    // base
    html,body{
      font-family: "Roboto", "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;
      font-size: 0.25rem;
      color: #555;
      width: 100%;
      height: 100%;
    }
    body,p,h1,h2,h3,h4,h5,h6{margin:0;}
    ul,ol{list-type:none; margin:0; padding:0;}
    // todo more ...
  3. 在js文件夾創建app.js並編寫代碼, 使用es6寫代碼就是舒服😊

    require('../lib/zepto.js');// zepto沒有使用CommonJs規範,修改後使用require引入 
    import { webApp } from '../lib/app/app.js'
    
    var App=webApp({
      container:'app',
      animate:{ effects:['slideInRight', 'slideOutLeft'],delay:600},
      preLoad:function(){
    
      },
      aftLoad:function(){
        loadPercent(100);
      }
    })
    .other('/index',{temId:'tempIndex',create:createIndex})
    .when('/button',{temId:'tempButton'})
    .when('/form',{temId:'tempForm'})
    .when('/dialog',{temId:'tempDialog',create:createDialog})
    .init();
    
    // todo: more ...
  4. 在template文件夾創建app.html,引用單頁面模板app-layout.html,並編寫內容,我這裏把單頁面的各個視圖代碼也以代碼塊的方式引入。

    {% extends '../layout/app-layout.html' %}
    {% block title %}Web App{% endblock %}
    {% block js %}
    <script src="./js/app.js"></script>
    {% endblock %}
    {% block content %}
    {% include './partial/index.html' %}
    {% include './partial/button.html' %}
    {% include './partial/dialog.html' %}
    {% include './partial/form.html' %}
    {% endblock %}
  5. 運行自動化命令,進行編譯,合併,壓縮,打包

    npm run build
  6. 最後項目文件都輸出到dist文件夾,找到app.html運行便可。

最後

代碼請看https://github.com/edwardzhong/project-template.git

相關文章
相關標籤/搜索