如今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" }
我這裏的angular
和angular-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.config.js
來命名webpack的配置文件,以避免和其餘配置文件搞混。可是因爲咱們通常都會分開開發環境和生產環境,而對於這個兩個環境打包咱們要求會有點不同。開發環境咱們但願它能夠直接模仿生產環境放上服務器測試;
而後又想它能夠一有改動就會自動打包更新顯示在頁面,不用咱們手動刷新瀏覽器;
不但願它打包花的時間太長;若是出錯會有相應的提示等等。而生產環境咱們想盡可能壓縮文件大小,生成manifest文件等等。所以,咱們就須要把開發打包和生產打包的配置分開來。這裏咱們就分開了 webpack.dev.config.js
和webpack.prod.config.js
兩個文件。可是仍是有些配置是兩個文件都會用到的,本着複用的精神,因此咱們還有一個 webapck.base.config.js
來記錄公共的配置。github
webpack的配置主要分爲幾個部分:web
這四個是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
有什麼問題或者不對的地方歡迎指出,謝謝閱讀!
本文原創,未經受權請勿轉載。