基於webpack構建的angular 1.x 工程(一)webpack篇

基於webpack構建的angular 1.x 工程(一)webpack篇

  如今AngularJS都已經出到4.x的版本了,可我對它的認識仍是停留在1.x的版本。
  以前用它是爲了搭配ionic來寫web手機天氣 應用(用來應付我大學裏一門學科的課設的︿( ̄︶ ̄)︿)。以後就由於它太難學而沒有繼續深刻下去。
  如今就任的公司也有個項目是作混合式的手機app的,竟然也是用AngularJS+ionic來作的,並且也是用1.x的版本。
  原本沒我什麼事的,我這段時間都在用Vuejs。而後上頭髮現那個項目加載是在太慢了,問我有沒有優化的方法。我看了下項目工程結構,發現是用gulp打包的一個工程。可能剛開始作這個項目的時候沒掌握好要點,致使整個項目臃腫不堪。gulp我是不會的了,因爲一直在用Vuejs,官方cli提供的模板就是用webpack打包的,並且我以前寫ReactJS用的也是webpack來打包的。所以,我就用了webpack來重構一下工程。而後寫下這篇詳細的文章,想給可能會一樣遇到的這種問題的朋友作一個參考( • ̀ω•́ )✧。 另外,本文也能夠當作webpack的一篇入門文章。css

首先,要先配置好工程文件。

  我先列一下個人package.json裏的配置:html

{
  "name": "angular-ionic-webpack",
  "version": "1.0.0",
  "description": "a project base on angular 1.x and webpack",
  "main": "index.js",
  "scripts": {
    "build": "webpack --config ./build/webpack.prod.config.js",
    "dev": "set NODE_ENV=dev&& webpack-dev-server --config ./build/webpack.dev.config.js"
  },
  "devDependencies": {
    "css-loader": "^0.26.4",
    "extract-text-webpack-plugin": "^3.0.1",
    "html-loader": "^0.4.4",
    "html-webpack-plugin": "^2.24.1",
    "style-loader": "^0.13.1",
    "url-loader": "^0.5.7",
    "webpack": "^3.1.0",
    "webpack-dev-server": "^2.9.2",
    "webpack-manifest-plugin": "^1.3.2",
    "webpack-merge": "^4.1.0"
  },
  "dependencies": {
    "angular": "1.4.3",
    "angular-cache": "^4.5.0",
    "angular-cookies": "1.4.12",
    "angular-ui-router": "^0.3.2",
    "jquery": "^3.2.1"
  },
  "author": "homer",
  "license": "MIT"
}

  第一個首先是項目直接用到的依賴,也就是dependencies裏的東西
分別有:vue

"dependencies": {
    "angular": "1.4.3", 
    "angular-cache": "^4.5.0",
    "angular-cookies": "1.4.12",
    "angular-ui-router": "^0.3.2",
    "jquery": "^3.2.1"
  }

  我這裏的angularangular-cookies都用了具體的版本(就是版本號前面沒有用符號^,直接寫數字1.4.3),由於不合版本的這兩個東西會跟ionic裏的angular-ui-router發生衝突致使渲染失敗。
  而我這裏也沒有裝ionic,是由於我直接引用的時候會報can't resolve 'ionic'的錯誤,我也不知道爲何,因此我是直接調用了/app/assets/lib裏的ionic.bundle.min.js來引入的。請有找到緣由的朋友麻煩告知一下我是爲何。 react

  接下來是開發時用到的依賴:jquery

"devDependencies": {
    "css-loader": "^0.26.4",
    "extract-text-webpack-plugin": "^3.0.1",
    "html-loader": "^0.4.4",
    "html-webpack-plugin": "^2.24.1",
    "style-loader": "^0.13.1",
    "url-loader": "^0.5.7",
    "webpack": "^3.1.0",
    "webpack-dev-server": "^2.9.2",
    "webpack-manifest-plugin": "^1.3.2",
    "webpack-merge": "^4.1.0"
  },

  各類loader是必要的,由於webpack在打包的時候會把你項目裏的非js文件轉換出來而後打包在一塊兒。咱們經常使用的loader有css-loader,url-loader,這兩個分別是解析css和圖片的。而後其餘的loader咱們要看項目需求來按需選取,好比我這裏由於是angular 1.x的項目,裏面還有挺多的html模板,因此我這裏用到了html-loader來解析html。
  其次是webpack——說句題外話,其實webpack通常都是用最新的,由於打包的環境跟所用的框架其實沒有太多互相干擾的地方。我一開始想着用的1.x的webpack發現用起來不怎麼方便,因而又改回最新的3.x。這也算是我的的一個小當心得吧。而後咱們還用了webpack-dev-server。這個是在咱們開發的時候用的服務器,能夠熱替換更新代碼。很方便,至於怎麼用我後面會詳細講。而後就是webpack-merge這個東西是用來合併webpack配置,這個是在vue項目裏看到,感受還挺好用,就也模仿着用了。最後就是各類插件,extract-text-webpack-plugin這個用來把css樣式獨立打包成一個css文件的插件,沒有它的話,樣式只會注入index.html作內聯樣式;html-webpack-plugin是用於把js注入到index.html裏;webpack-manifest-plugin是用來生成網頁的manifest文件的。
  而後是寫啓動webpack的命令行,也就是上面的:webpack

"scripts": {
    "build": "webpack --config ./build/webpack.prod.config.js",
    "dev": "set NODE_ENV=dev&& webpack-dev-server --config ./build/webpack.dev.config.js"
  },

這樣寫的意思是,當你輸入npm run + 你的命令名字就會讓npm執行你對應命令的語句。好比輸入npm run dev,至關於你執行了上面那條dev對應的set NODE_ENV=dev&& webpack-dev-server --config ./build/webpack.dev.config.js"這條語句。這裏dev命令執行的是開發版本打包並生成開發的服務器;build命令執行的則是生產版本打包。在打包開發版本的時候,用的是webpack-dev-server,咱們讓它按照./build/webpack.dev.config.js裏的配置(下文會提到)來執行。在打包生產環境,是直接運行webpack,讓它按照./build/webpack.prod.config.js裏的配置來執行。 git

  關於這份package.json裏其餘的配置有問題的能夠在評論裏提哈~~angularjs

而後來寫webpack的配置文件

概述

  安裝了webpack,咱們要配置好,讓它按照咱們的指望來工做。
通常咱們都會用 webpack.config.js來命名webpack的配置文件,以避免和其餘配置文件搞混。可是因爲咱們通常都會分開開發環境和生產環境,而對於這個兩個環境打包咱們要求會有點不同。開發環境咱們但願它能夠直接模仿生產環境放上服務器測試;
而後又想它能夠一有改動就會自動打包更新顯示在頁面,不用咱們手動刷新瀏覽器;
不但願它打包花的時間太長;若是出錯會有相應的提示等等。而生產環境咱們想盡可能壓縮文件大小,生成manifest文件等等。所以,咱們就須要把開發打包和生產打包的配置分開來。這裏咱們就分開了 webpack.dev.config.jswebpack.prod.config.js兩個文件。可是仍是有些配置是兩個文件都會用到的,本着複用的精神,因此咱們還有一個 webapck.base.config.js來記錄公共的配置。github

webpack基本結構

  webpack的配置主要分爲幾個部分:web

  1. webpack打包文件的入口(entry)。
  2. webpack打包完文件後輸出的出口(output)。
  3. webpack在打包文件時的模塊配置(module)。
  4. webpack在打包文件時用到的插件(plugin)。

  這四個是webpack配置的基本部分,寫好了這四個基本能夠打包成功了。
還有其餘要用的配置後面會說到,其餘配置沒用到的能夠看一下官方的文檔(3.x的官網)/ (我的以爲翻譯的比較好的中文文檔)。接下來咱們先來分析下開發環境和生成環境共用的部分配置。首先入口文件通常都是同樣的吧?而後打包時模塊配置也是同樣的,由於你打包時的文件都是同樣的,因此設置也是同樣的。因此咱們webpack.base.config.js是這樣寫的:

var path = require('path');
var root = path.resolve(__dirname, '../');

module.exports = {
    entry: {
        'main': root + '\\app\\index.js',
        jquery:['jquery'],
        ionic:root+'\\app\\assets\\lib\\ionic\\release\\js\\ionic.bundle.min.js',
        datepicker:root+'\\app\\assets\\lib\\ionic-datepicker\\release\\ionic-datepicker.bundle.min.js',
        calendar_pk:root+'\\app\\assets\\lib\\calendar-pk\\release\\js\\calendar_pk.min.js'
    },
    module: {
        loaders: [
            {
                test: /\.(png|jpe?g|gif|woff|svg|eot|ttf)(\?.*)?$/,
                loader: 'url-loader',
                query: {
                    limit: 10000,
                }
            },
            {
                test: /\.html$/,
                loader: 'html-loader'
            }

        ]
    },
    resolve: {
        extensions: ['.js', '.json']
    }

};

  入口(entry)文件其實不必定是隻有一個,我這裏就有多個。只要路徑分開寫正確就能夠了。
  而後是模塊(module)配置,webpack的思想是把工程全部的js都是模塊,而後所有打包在一塊兒。因此遇到一些非js會有麻煩。可是他們早就預料這種狀況,作出了一些系列的loader(加載器)來把一些非js文件作成webpack能打包的東西。
通常都會用到的是css-loader, url-loader。這兩個分別用來解析項目裏.css和圖片字體之類的文件。上面說過,因爲項目中會有較多的.html文件要引用,因此咱們還用了 html-loader。我這裏還有一個 resolve(解析)的配置,這個是用來js裏引用文件的時候,不寫後綴的話,webpack就會自動爲其加上.js或.json的後綴,能夠省一些寫後綴的時間(✧◡✧)。

開發打包配置

  咱們的開發打包配置是這樣的:

var baseconf = require('./webpack.base.config');
var merge = require('webpack-merge');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpack = require('webpack');
var server = require('./configDevServer');
var path = require('path');
var root = path.resolve(__dirname, '../');

var plugins = [
    new webpack.DefinePlugin({
        'process.env': {
            NODE_ENV: JSON.stringify("development")
        }
    }),
    new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        }
    }),
    new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery',
        'window.jQuery': 'jquery',
        'window.$': 'jquery'
    }),
    new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor', // 這公共代碼的chunk名爲'commons'
        filename: '[name].bundle.js', // 生成後的文件名,雖然說用了[name],但實際上就是'commons.bundle.js'了
        minChunks: 3, // 設定要有4個chunk(即4個頁面)加載的js模塊纔會被歸入公共代碼。這數目本身考慮吧,我認爲3-5比較合適。
    }),
    new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.html',
            inject: true
    }),
    new webpack.HotModuleReplacementPlugin()
];
baseconf.module.loaders.push(
    {
        test: /\.css$/,
        loader: ['style-loader','css-loader'],
    }
);
module.exports = merge(baseconf, {
    output: {
        path: root+"/dist",
        publicPath: "/",
        filename: "./js/[name].[chunkhash].js"
    },
    devtool: 'cheap-module-eval-source-map',
    devServer: server,
    plugins: plugins,
});

  咱們首先把基本的配置引進來。而後寫插件(plugin),畢竟咱們開發配置想實現的功能有部分須要插件來作。
webpack.DefinePlugin是用來讓webpack知道正在準備的是開發環境打包。某些框架會識別開發和生產環境,而後在咱們開發的時候會給出相應的警告和提示,而在生產環境則會屏蔽這些內容。webpack.ProvidePlugin是當咱們用到 jQuery之類的js庫的時候,用到的相關符號都會自動進行引用,不會致使報錯。webpack.optimize.CommonsChunkPlugin是用來提取咱們代碼裏的公共用到的部分,避免代碼重複打包,減小代碼體積。webpack.HotModuleReplacementPlugin是用來啓用咱們的代碼熱替換功能,在咱們改了代碼以後開發服務器能夠從新打包更新,瀏覽器自動刷新,把咱們的改動顯示在頁面。HtmlWebpackPlugin是咱們本身安裝的插件,用來把生成的js自動插入到咱們的html模板裏面。
  寫完了插件以後,咱們還要寫輸出(output)。這裏指定下輸出文件夾和輸出的js名字便可。而後是是開發工具(devtool)和開發服務器(dev-server),開發工具的意思是,webpack會根據打包的文件作出一個標識的map文件,若是代碼出錯的話,它會找出來,而後提示在什麼地方。方便修改代碼。開發服務器是一個創建在本地的服務器,上面就是你的項目。搭配熱替換功能,開發會很方便。這裏順帶簡單介紹下,開發服務器配置 ./build/configDevServer.js

const server={
    contentBase:'/dist/',
    host: 'localhost',//服務主機
    port: 8089,//端口
    inline: true, // 能夠監控js變化
    hot: true, // 熱啓動
    compress: true,
    watchContentBase: true,
    proxy: {//設置代理服務器,用於調試接口
        '/api':{
            target:'http://www.baidu.com',
            pathRewrite:{"^/api": "/api"}//重寫路徑
        }
    }
};
module.exports= server;

  能夠看上面的備註來理解對應的配置項的意思。
  上文咱們裝了個 webpack-merge這時就發揮做用了。正如它的名字同樣,它會把兩個webpack配置合併起來。而後輸出。這樣咱們的開發環境配置寫好了

生產環境配置

  一樣,先上配置:

var baseconf = require('./webpack.base.config');
var path = require('path');
var root = path.resolve(__dirname, '../');
var merge = require('webpack-merge');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpack=require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var ManifestPlugin = require('webpack-manifest-plugin');
var plugins = [
    new webpack.DefinePlugin({
        'process.env': {
            NODE_ENV:JSON.stringify("development")
        }
    }),
    new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        }
    }),
    new HtmlWebpackPlugin({
        filename: 'index.html',
        template: 'index.html',
        inject: true
    }),
    new ExtractTextPlugin({
        filename: './css/[name].css?[contenthash:8]',
        allChunks: true,
    }),
    new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery',
        'window.jQuery': 'jquery',
        'window.$': 'jquery',
    }),
    new webpack.optimize.CommonsChunkPlugin({
        name: 'commons', // 這公共代碼的chunk名爲'commons'
        filename: './js/[name].bundle.js', // 生成後的文件名
        minChunks: 3,
    }),
    new ManifestPlugin(path.join('dist', 'manifest.json'))
];
baseconf.module.rules.push(
    { test: /\.css$/,
        loader: ['style-loader','css-loader'] }
);
module.exports=merge(baseconf,{
    output: {
    path: root+"/dist",
        publicPath: "./",
        filename: "./js/[name].[chunkhash].js"
},
    devtool: false,
    plugins: plugins
});

  重複的插件咱們就不說了,咱們說說幾個上面沒有的插件。 webpack.optimize.UglifyJsPlugin是用來壓縮混淆js代碼的。ExtractTextPlugin是咱們另外安裝的,用來把打包的css獨立出來成一個css文件。使用這個插件的時候,css的loader要相應作一下設置,因此能夠看到 css-loader我沒有放到公共配置,裏面而是分開了。ManifestPlugin也是另外安裝的,用來生成manifest緩存文件,使網站能夠減小對靜態資源的重複請求。另外你能夠發現這裏devtool設成了false,沒有設置devserver,由於不是生產所須要的,因此沒有設置。

來跑一遍吧!

在你的入口的地方創建一個配置裏的entry規定名字的js文件,就能夠先跑一遍webpack。
若是webpack沒有報錯,就說明你的配置基本是對的。

接下來,我會就angular 1.x 用webpack打包打包遇到的坑來講一說,請看下一篇文章:

基於webpack構建的angular 1.x工程(angular篇)

想看詳細代碼,能夠訪問個人項目地址
https://github.com/homerious/angular-ionic-webpack

有什麼問題或者不對的地方歡迎指出,謝謝閱讀!

本文原創,未經受權請勿轉載。

相關文章
相關標籤/搜索