【秒懂】用 Javascript 做 Routing——讓 Single-page webapp 不用 Hashbang (#!) 也能瀏覽


  _     _             _ ____    ____             _   _             
 | |__ | |_ _ __ ___ | | ___|  |  _ \ ___  _   _| |_(_)_ __   __ _ 
 | '_ \| __| '_ ` _ \| |___ \  | |_) / _ \| | | | __| | '_ \ / _` |
 | | | | |_| | | | | | |___) | |  _ < (_) | |_| | |_| | | | | (_| |
 |_| |_|\__|_| |_| |_|_|____/  |_| \_\___/ \__,_|\__|_|_| |_|\__, |
                                                             |___/

【簡介】

做 Single-page webapp 最大的問題就是不能像普通鏈接一樣:

所以,現在要做的是:

  1. 讓網頁的內容能透過 (e.g.) http://www.example.com/webapp/login 來分享
  2. 讓【上一頁】按鈕能運作,真的返回先前的狀態

但,要注意的是:

  1. 網頁一定要透過 Javascript 才能執行
    • 如果要照顧沒有 Javascript 的瀏覽器用戶,只能把整個網頁用 Server-side programme 重寫
  2. 不支援HTML5 的瀏覽器,也可以瀏覽網頁,但
    • 網址還是會有 #!
    • 不能使用【上一頁】、【下一頁】的按鈕

【事前功夫】

  1. 要有已經設定好的 Server:以下的教學會分別說明 Apache 跟 Nginx
  2. 為了簡化內容(還有小弟的技術不足, haha),以下內容用上 Javascript Framework  (e.g.)AngularJS,EmberJS,BareboneJS
    • 在這裡,會以 AngularJS 為目標
  3. 支援 html5 的瀏覽器,尤其是支援 【History.pushState】

【秒懂步驟~開始】

下面的教學,會以一下的設置做背景

  • Server: Apache/ Nginx
  • Website Path: /webapp/exampleApp/
  • 所以內部瀏覽的網址是: 127.0.0.1/webapp/exampleApp

以下內容將會一氣呵成,需要解釋的可以再留言區問~

【1.0.1|後台 / 設置 / Apache】

  1. 設定好 Apache 的 httpd.conf,讓 Apache 支援 mod_rewrite

【1.0.2|後台 / 設置 / Nginx】

  1. 在 nginx.conf 的【Server {…}】裡面加上:
    location /webapp/exampleApp {
        index index.php index.html index.htm;
        try_files $uri $uri/ /webapp/exampleApp/index.html;
    }
    

【2.0.1|前台 / 設置 / Apache】

  1. 在 Website Path 的檔案夾裡加上 .htaccess 檔案內容如下:
    # html5 pushstate (history) support: 
     
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_URI} !index
        RewriteRule (.*) index.html [L]
    

【2.1 |前台 / 設置 / HTML】

  1.  在 /webapp/exampleApp/index.html 的 … 加上一個  element:
    <base href="webapp/exampleApp/">

【2.2|前台 / 注意 / HTML + Javascript】

  1.  HTML 裡的所有虛擬 鏈接【】 (e.g.) http://www.example.com/webapp/exampleApp/login 的 【/login】都需要用以下方式寫:
    <a href="#!/login">(e.g.) Login Here</a>
  2. 如果不是透過【超鏈接打開的】 (e.g.) 按了【Button】,彈出登入界面,但不想 reload 網頁+可以傳送鏈接
    • 在 Button Function 的 Javascript Code 裡加上:
      window.history.pushState(page_name, document.title, full_path);
    • (e.g.)
      window.history.pushState("Login Form", "Login Form | exampleApp", "/webapp/exampleApp/login");

【3.0|前台 / Routing – AngularJS】

因為只有接觸過AngularJS,所以以 AngularJS 做例子,其他的 Framework 的做法也大同小異~

  1. 在 index.html 聯繫上【angularJS + angularJS 的ngRoute module + 自己寫的AngularJS 的 JS 檔】
    <script src="assets/js/base/angular.min.js"></script>
    <script src="assets/js/base/angular-route.min.js"></script>
    <script src="assets/js/ng_JS.js"></script>
  2. 在 index.html 加上【ng-app + ng-controller + ng-view】
    exampleApp">...
    
     
  3. 【ng_JS.js】——控制 Routing 的 Controller
    var exampleApp = angular.module('exampleApp', ['ngRoute']);
    exampleApp.config(function($routeProvider, $locationProvider) {
        // Manages routing
        $routeProvider.when('/', {
            templateUrl: 'pages/home.html',
            controller: 'mainController',
        }).when('/login', {
            controller: 'loginController',
            pageTitle: 'loginForm'
        }).otherwise({
           redirectTo: '/'
        });
    // Enable html5Mode for pushstate ('#'-less URLs)
        $locationProvider.html5Mode(true);
        $locationProvider.hashPrefix('!');
    });
  4. 【ng_JS.js】—— Controller 的程序
    exampleApp.controller('mainController', function($scope) {
        $.getScript("assets/js/web_mainJS.js").done(function() {
            // Dirty-way to get JS for the main page, and start processing
        });
    });
    exampleApp.controller('loginController', function($scope) {
        $.getScript("assets/js/web_loginJS.js").done(function() {
            // Dirty-way to get JS for the login form, and start processing
            pop_login_form(); // Popup the login form when the link (/login) is routed
        });
    });

 【總結】

以上的教學實屬片面,只是 Concept-proof 的程度,但掌握了這樣的 Routing 課真的有用至極了,尤其是喜歡寫 Webapp 的人,免卻了對 Server 的負載!

參考文章:

  1. Single Page Apps with AngularJS Routing and Templating ♥ Scotch
  2. Angularjs Apache Rewrite Rule for HTML5Mode
  3. HTML5: Changing the browser-URL without refreshing page

Please leave your comments below if you have any question 😀

塗牆

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s