雖然一直有寫前端,並且水平自認上升很快,可是仍然沒有玩過模塊化開發。javascript
對於前端的這些工具也沒有接觸過,平時通常都是vs和vs code就搞定了,爲了搞一搞模塊化開發,準備來玩一下這些前端工具。css
因此寫寫這些前端工具的安裝步驟,記錄一下之後忘了也能用,若是能幫到別人就更好了。html
安裝node.js後,自動就安裝了npm,因此這裏二者寫到一塊兒了。前端
nodejs的下載地址:java
https://nodejs.org/en/download/node
這種東西給個下載地址就行了,根據本身電腦類型安裝,作程序員的也沒有電腦小白,下一步就不說了。webpack
npm在這裏被我理解爲一個下載工具,而下載的地址爲https://www.npmjs.com 。程序員
只不過在國內訪問不穩定,所以建議使用國內鏡向站點https://npm.taobao.org 。web
在cmd.exe中,運行如下命令便可:npm
npm --registry https://registry.npm.taobao.org info underscore
或者找到Nodejs安裝文件夾中的npmrc文件,在該文件中加入
registry = https://registry.npm.taobao.org
gulp用來優化前端工做流程。
npm install gulp -g
輸入gulp -v能夠查看到相應版本
如下是我用vs code本身建的一個項目:
命令行cd到本身建的項目文件夾,而後npm init便可生成本身的package.json,這是本身項目的每一個項目的一個描述文件,定義了這個項目所須要的各類模塊,以及項目的配置信息(好比名稱、版本、許可證等元數據)。
npm install gulp --save-dev
安裝後:
此時項目中多了node_modules這個文件夾,同時package.json中自動寫入了devDependencies字段,並在該字段下填充了gulp模塊名。
接下來安裝上面gulp中可用的一堆插件
npm install --save-dev gulp-uglify gulp-concat gulp-imagemin gulp-htmlmin gulp-clean-css gulp-rev-append gulp-autoprefixer
安裝後:
gulp-uglify爲壓縮js文件,gulp-concat爲合併打包文件,gulp-imagemin爲壓縮圖片,gulp-htmlmin爲壓縮html,gulp-clean-css壓縮css文件,gulp-rev-append爲添加版本號。
實際上.NET MVC的bundle繼承了上面這些功能,因此用.net進行開發貌似徹底用不到,不過想來別的語言也許應該仍是須要的。
而gulp-autoprefixer是根據設置瀏覽器版本自動處理瀏覽器前綴,gulp-less插件將less文件編譯成css,當有less文件發生改變自動編譯less,並保證less語法錯誤或出現異常時能正常工做並提示錯誤信息。
確定仍是有一些別的功能的插件,這只是我暫時瞭解到的幾個,若是有其它好用的也但願有大神能留言告訴我一下。
若是要用這些插件,那麼還要在根目錄下加一個gulpfile.js配置文件,如下爲我本身的測試項目:
根據測試項目寫的配置文件:
/*引入gulp及相關插件 require('node_modules裏對應模塊')*/ var gulp = require('gulp'); var minifyCss = require("gulp-clean-css"), uglify = require('gulp-uglify'), concat = require('gulp-concat'), imagemin = require('gulp-imagemin'), htmlmin = require('gulp-htmlmin'), rev = require('gulp-rev-append'), autoprefixer = require('gulp-autoprefixer'), less = require('gulp-less'); //壓縮html,並給頁面的引用添加版本號,清除頁面引用緩存 gulp.task('minifyHtml', function() { var options = { removeComments: true, //清除HTML註釋 collapseWhitespace: true, //壓縮HTML collapseBooleanAttributes: true, //省略布爾屬性的值 <input checked="true"/> ==> <input /> removeEmptyAttributes: true, //刪除全部空格做屬性值 <input id="" /> ==> <input /> removeScriptTypeAttributes: true, //刪除<script>的type="text/javascript" removeStyleLinkTypeAttributes: true, //刪除<style>和<link>的type="text/css" minifyJS: true, //壓縮頁面JS minifyCSS: true //壓縮頁面CSS }; gulp.src('examples/*.html') .pipe(htmlmin(options)) .pipe(rev()) .pipe(gulp.dest('dist/html')); }); //壓縮圖片 gulp.task('minify-img', function() { gulp.src('src/img/*.{png,jpg,gif,ico}') .pipe(imagemin()) .pipe(gulp.dest('dist/img/')); }); //編譯less gulp.task('handleLess', function() { gulp.src('src/less/*.less') .pipe(less()) .pipe(gulp.dest('src/css')); }); //設置瀏覽器版本自動處理瀏覽器前綴,並壓縮css gulp.task('minify-css', function() { gulp.src('src/css/*.css') .pipe(autoprefixer({ browsers: ['last 2 versions', 'Android >= 4.0'], cascade: true, //是否美化屬性值 默認:true 像這樣: //-webkit-transform: rotate(45deg); // transform: rotate(45deg); remove: true //是否去掉沒必要要的前綴 默認:true })) .pipe(minifyCss()) .pipe(gulp.dest('dist/css/')); }); //打包並壓縮js gulp.task('minify-script', function() { gulp.src('src/js/*.js') .pipe(concat('helloworld.js')) //打包 .pipe(uglify()) //壓縮 .pipe(gulp.dest('dist/js/')); }); gulp.task('default', ['minifyHtml', 'minify-img', 'handleLess', 'minify-css', 'minify-script']);
根據上面的配置咱們能夠在命令行輸入 :
gulp minify-script
這就只打包壓縮JS文件,也能夠輸入:
gulp minify-script
這樣就完成咱們全部的構建工做。
進一步的學習能夠轉到:http://www.gulpjs.com.cn/
webpack是一個前端模塊化方案,只不過是本地的,而相似requireJs和sea.js是在線模塊化方案。
有了上面安裝gulp的經驗webpack就簡單多了。
安裝webpack :
npm install webpack -g
接下來增長package.json配置文件,也就是
npm init
只不過咱們前面配置了,那麼直接下一步:
npm install webpack --save-dev
一樣這個webpack也會加到node_modules文件夾中。
那麼來一段簡單的前端示例,使用webpack來實現前端模塊化,我有兩個文件:
hello.js
window.resize = function() { console.info("我resize了!"); }
helloApp.js
var hello = require('./hello.js');
console.log(hello);
雖然不清楚語法,可是大概也能明白,helloApp.js引用了hello.js。
運行
webpack src/js/helloApp.js dist/js/helloApp.Main.js
而後生成的helloApp.Main.js是下面這個樣子:
/******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // identity function for calling harmony imports with the correct context /******/ __webpack_require__.i = function(value) { return value; }; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 1); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports) { window.resize = function() { console.info("我resize了!"); } /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { var hello = __webpack_require__(0); console.log(hello); /***/ }) /******/ ]);
一大段代碼看着就很捉急,不過實際上看看也不過就是個當即執行函數,我刪減了一些代碼,並進行了一些格式化,如下是個人代碼:
(function(modules) { //將咱們兩個文件中的代碼做爲一個函數對象傳進這裏 //而後進行某些處理 }) ( [ ( function(module, exports) { //仔細對照,這是咱們被引用的hello.js的代碼 window.resize = function() { console.info("我resize了!"); } } ), ( function(module, exports, __webpack_require__) { //仔細對照,這是咱們的helloApp.js的代碼, //只不過require被換位了__webpack_require__ //而裏面的路徑'./hello.js'被換位了0,哈,簡單猜測一下,這個0就是咱們hello.js的代碼所在的函數對象,在傳進去的moudles數組中所在的索引 var hello = __webpack_require__(0); console.log(hello); } ) ] );
而後咱們加入部分被刪掉的代碼:
(function(modules) { // The module cache /******/ var installedModules = {}; /******/ // The require function //(2)第二步看第一步調用的這個函數,果真1就是moduleId /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache // 查看模塊緩存中有不有moduleId爲1的,有就直接返回installedModules[moduleId].exports // 讀到這裏只知道起到個緩存的做用,先無論這個是什麼鬼,下一步 /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) // 走到這裏,確定表示沒緩存嘛,因而建立下面這個對象 // 這個對象的i爲入口模塊索引, // l是false,不知道什麼鬼無論, // exports就是輸出對象嘛,同時將這個對象的引用交給了installedModules[moduleId]和module // 也就是說這個對象咱們緩存了 /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function // 來到了有趣的地方,modules是咱們傳進來的模塊數組,modules[moduleId]就是咱們的入口函數,也就是下面這個: // ( // function(module, exports, __webpack_require__) { // hello = __webpack_require__(0); // console.log(hello); // } // ) // 那麼運行下面代碼的大體效果就是: // var entryModule=function(module, exports, __webpack_require__) { // hello = __webpack_require__(0); // console.log(hello); // }; // entryModule(module,module.exports,__webpack_require__); // 這段代碼的就厲害了,又執行了__webpack_require__這個函數,不過此時的參數爲0,也就是咱們那個被引用的js的代碼的函數對象的索引 /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded // 此時咱們瞭解到l的做用表示這個模塊是否被加載 /******/ module.l = true; /******/ /******/ // Return the exports of the module // 而後返回 module.exports, // 若是此時是hello.js的代碼運行完,那麼此時就會將hello.js中給形參exports的部分返回給hello那個變量 // 此時我就明白了,webpack在不一樣的js之間如何創建依賴關係 // 讓被引用的部分只返回但願返回的部門,放到exports中,供引用的js調用 /******/ return module.exports; /******/ } /******/ /******/ // Load entry module and return exports // (1)第一步,看上面自帶的註釋,表示:這是載入入口模塊,而且返回輸出 // 這個入口模塊什麼的,給了個s什麼的,而後給了它個1,這裏的s暫時看着沒什麼用啊 // 那麼就當作__webpack_require__(1)就行了 // 這個1的話咱們猜想就是傳進來的module數組中那個引用其餘js的helloApp.js的代碼的函數對象的索引 /******/ return __webpack_require__(__webpack_require__.s = 1); }) ( [ ( function(module, exports) { //仔細對照,這是咱們被引用的hello.js的代碼 window.resize = function() { console.info("我resize了!"); } } ), ( function(module, exports, __webpack_require__) { //仔細對照,這是咱們的helloApp.js的代碼, //只不過require被換位了__webpack_require__ //而裏面的路徑'./hello.js'被換位了0,哈,簡單猜測一下,這個0就是咱們hello.js的代碼所在的函數對象,在傳進去的moudles數組中所在的索引 hello = __webpack_require__(0); console.log(hello); } ) ] );
OK,到了這裏,我對webpack的大體功能就有了一個瞭解~~~~~。
這不就跟咱們在.net或者java中的using或import同樣嘛,而上面這個這個東西就是咱們的Main函數,果真,沒什麼高大上的,其實就是這麼簡單。
接下來就去了解一下webpack的具體配置,首先新建一個webpack.config.js文件,而後讓打包簡單化:
module.exports = { entry: './src/app.js', output: { path: './dist', filename: 'app.bundle.js' } };
而後直接運行webpack命令便可,就至關於自動去找webpack.config.js文件,而後根據文件中的入口app.js去生成app.bundle.js。
到這裏意思就很明白了,webpack實際上就是一個相似Seajs、RequireJS同樣的東西。
接下來的工做貌似就是去查webpack的如何去配置什麼的了,這種細枝末節的這裏就不講了。
貌似這是一個安裝的帖子 ~~~