由webpack引起的前端自動化講解

記念第一次講課,記念 avepont ,記念長春,記念倆年前青澀的本身,記念windows,本文是兩年前第一次講課所準備的課件。javascript

對NODE的誤解

  • NODE 確定是幾個前端工程師在實驗室裏搗鼓出來的。
  • 爲了後端然後端,有意思嗎?
  • 怎麼又發明了一門新語言?
  • javascript 承擔的責任過重了
  • 直覺上,JavaScript不該該運行在後端
  • 前端工程師要逆襲了

圖靈完備語言

一切可計算的問題都能計算,這樣的虛擬機或者編程語言就叫圖靈完備的。css

一個能計算出每一個圖靈可計算函數(Turing-computable function)的計算系統被稱爲圖靈完備的。一個語言是圖靈完備的,意味着該語言的計算能力與一個通用圖靈機 (Universal Turing Machine)至關,這也是現代計算機語言所能擁有的最高能力。html

如今的計算機編程語言都是圖靈徹底(完備)的。前端

所以,這世上也不存在一種語言能夠作,而另外一種語言不能夠作的事兒java

NODE

Ryan Dahl 是一名資深的程序員,在創造出NODE以前,他的主要工做都是圍繞高性能Web服務器進行的。經歷過一些嘗試和失敗以後,他找到了設計高性能Web服務器的幾個要點:事件驅動,非阻塞I/O.node

通過C,Lua,Haskell,Ruby,javascript等權衡最終選擇的了javascript。python

起初,Ryan Dahl稱她的項目爲web.js,就是一個Web服務器,可是項目的發展超過了他最初構想,變成了一個構建網絡應用的基礎框架。每一個NODE進程都構成網絡應用中的一個節點,這就是NODE名字所含意義的真諦。react

雖然NODE這麼酷炫可是咱們都不用咱們只用它寫腳本。webpack

Chrome&Node

NODE&Browser&W3C&ECMASCRIPT

NPM

npm 即node的安裝包管理工具(就像nuget之於.NET,pip之於python)git

npm 命令手冊

  • npm -v 顯示版本信息
  • npm install [--save]?
$ npm install sax@latest
$ npm install sax@0.1.1
$ npm install sax@">=0.1.0 <0.2.0"
複製代碼
  • npm update
  • npm -l //查看每一個命令的用法
  • npm info npm
  • npm run

npm install eslint uglify-js --save

"scripts": {
  "lint": "eslint script.js ",
  "compile": "babel script.js",
  "uglifyjs ":"uglifyjs inet.js -o inet-min.js",
  "template": "node bin/templete.js",
  "launch": "launch.cmd",
  "build":"npm run lint &&npm run compile&&npm run launch",
  ""
},

複製代碼

指令&數據

這兩個概念在計算機世界無處不在,通常數據的載體的就是文件,而這個文件在必定的環境下又變成了指令。如:一個HTML文件放在服務器上就是數據,而當瀏覽器獲取了它,並將其解析絢麗的頁面它就成了指令。

而前端主要由三種數據組成,HTML,CSS,JS,所以前端自動化就是用腳步自動化處理前端所涉及的數據(文件)。

而這個腳步呢就用NODE寫,其一前端開發對JS技術栽比較熟悉容易上手,其二NODE社區灰常活躍你基本能找到你想要的全部東西。

不過你們在網上檢索前端自動化,基本都會感受前端自動化是grunt,gulp,webpack...,或者由於NODE纔有了前端自動化。

其實一直都存在,只是以前更多的是java,python...的實現,就像如今找尋一些工具基本也都是java,python,ruby 版的。

前端自動化都作什麼

  • 壓縮CSS,js。
  • 預編譯HTML,JS,CSS 前端涉及到的語言。HTML ,CSS 抽象程度比較低爲了更高效的開發通常 HTML,css 由 jade,less 等DSL(Domain Specific Language)編譯而成。
  • 語法檢查,格式整理,自動刷新頁面等其它功能。 當前主流的全部工具,基本都會提供兩種調用方式: CLI & NODEAPI

命令行程序

PATH

PATH=
C:\Windows\system32;
C:\Windows;C:\Windows\System32\Wbem;
C:\Windows\System32\WindowsPowerShell\v1.0\;
C:\Program Files (x86)\nodejs\;
C:\Program Files\Git\cmd;
C:\Program Files\dotnet\;
C:\Program Files\TortoiseGit\bin;C:\Users\Zhuo.Li\AppData\Local\Programs\Python\Python35\Scripts\;
C:\Users\Zhuo.Li\AppData\Local\Programs\Python\Python35\;
C:\Users\Zhuo.Li\AppData\Roaming\npm;
複製代碼

PATHEXT

C:\Users\Zhuo.Li>echo %PATHEXT%
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
複製代碼

Hello World

echo  Hello World
複製代碼

node 全局命令調用方式

@IF EXIST "%~dp0\node.exe" (
  "%~dp0\node.exe"  "%~dp0\node_modules\gulp\bin\gulp.js" %*
) ELSE (
  @SETLOCAL
  @SET PATHEXT=%PATHEXT:;.JS;=;%
  node  "%~dp0\node_modules\gulp\bin\gulp.js" %*
)
複製代碼

模塊組織

隨着javascript發展,從加強顯示的腳本到解決一類問題的庫,而後構建應用,一個有效的模塊加載方案也就成爲了必須的元素。 由於當想用一個語言構建一個大型應用,模塊機制不可或缺。

  • 瀏覽器端運用最普遍的爲 AMD 規範
  • 服務端使用 CommonJS 規範
  • 而ES6 Module 加載規範不遠的未來將要統一先後端(咱們要是採用ES6 加載規範)

-javascript模塊化編程

require AMD 寫在回調中是由於若是同步等他瀏覽器可能會卡死.

關於javascriptIDE 目前功能薄弱的思考

javascript 尤爲運行在瀏覽器端並沒標準統一的入口,經過簡陋的<script>標籤引入,因此沒法判斷一個文件中出現的對象該有何種行爲,並且script 還多是動態加載的。 必然不能像其餘語言那樣智能檢驗差錯與提示,若是之後模塊化編程根深蒂固,javascriptIDE也會像其餘語言同樣強大。 有必要的話興許還能實時預覽,由於如今集成webkit渲染引擎開發桌面的應用正在蓬勃發展(好比我正在使用的vscode)

AMD

define(['module1', 'module2'], function(m1, m2) {

    return {
        method: function() {
            m1.methodA();
			m2.methodB();
        }
    };

});

require(['foo', 'bar'], function ( foo, bar ) {
        foo.doSomething();
});
複製代碼

cmomonjs

//index.js
const m1=require("module1");

m1.dosomething()
.........

//module1
......

module.exports={
dosomething:function(){
    ....
}
}

複製代碼

ES6

import

//import
import { stat as _stat, exists, readFile } from 'fs';
//因爲import是靜態執行,因此不能使用表達式和變量,這些只有在運行時才能獲得結果的語法結構。

// 報錯
import { 'f' + 'oo' } from 'my_module';

// 報錯
let module = 'my_module';
import { foo } from module;

// 報錯
if (x === 1) {
  import { foo } from 'module1';
} else {
  import { foo } from 'module2';
}
//上面三種寫法都會報錯,由於它們用到了表達式、變量和if結構。在靜態分析階段,這些語法都是無法獲得值的。
複製代碼

export

export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
//上面代碼是profile.js文件,保存了用戶信息。ES6 將其視爲一個模塊,裏面用export命令對外部輸出了三個變量。

//export的寫法,除了像上面這樣,還有另一種。

// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;

export {firstName as _firstName, lastName, year};


複製代碼

export default

/ export-default.js
export default function () {
  console.log('foo');
}
上面代碼是一個模塊文件export-default.js,它的默認輸出是一個函數。

其餘模塊加載該模塊時,import命令能夠爲該匿名函數指定任意名字。

// import-default.js
import customName from './export-default';
customName(); // 'foo'
複製代碼

aui.js

"use strict";

var aui ={
    version:'1.0.0'
}
function func(){

    return aui.version;
}
//export default aui;
export default func;
複製代碼

widget.js

var combobox = {
    name:'combobox'
}

var dialog = {
    name:'dialog'
}

export { combobox,dialog}
複製代碼

index.js

import aui from './aui';

import {combobox,dialog as _dialog} from './widget';

console.dir(combobox.name);

console.log(_dialog.name);

console.dir(func());
複製代碼

index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="./lib/library1"></script>
    <script src="./lib/library2"></script>
    <script src="global.common.js"></script>
    <title>React App</title>
  </head>
  <body>
    <div id="root"></div>
   
    <script type="text/javascript" src="index.js"></script>
  </body>   
</html>
複製代碼

webpack

webpack 是一個現代的 JavaScript 應用程序的模塊打包器(module bundler)。當 webpack 處理應用程序時,它會遞歸地構建一個依賴關係圖表(dependency graph),其中包含應用程序須要的每一個模塊,而後將全部這些模塊打包成少許的 bundle - 一般只有一個,由瀏覽器加載。

它是高度可配置的,可是,在開始前你須要先理解四個核心概念:入口(entry)、輸出(output)、loader、插件(plugins)。

使用配置文件的用法 webpack [--config webpack.config.js]

$ webpack --config example.config.js
複製代碼

不使用配置文件的用法 webpack []

$ webpack src/index.js dist/bundle.js
複製代碼

NODE API

const webpack = require("webpack");

webpack({
  // 配置對象
}, (err, stats) => {
  if (err || stats.hasErrors()) {
    // 在這裏處理錯誤
  }
  // 處理完成
});
複製代碼

webpackConfig

//webpack.config.js

var pkg = require("./package"),
    options = process.argv,
    config;

/** * pkg.pattern {dev|prod} 原計劃package.json 中配置是否爲product 目前沒有使用 */
config = require("./webpack." + pkg.env);
module.exports = config;
複製代碼
//var webpack = require('webpack');
var path = require("path"),
    HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    entry: {
        bundle: "./src/hello.js",
        // react:"./src/react.js",
        index:"./webpack_demo/index.js"
    },
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: "[name].js"

    },
    module: {
        rules: [
            // {
            // test: /\.js$/,
            // enforce: "pre",
            // loader: "eslint-loader"
            // },
            {
                test: /\.js$/,
                exclude: /(node_modules)/,
                use: [{
                    loader: 'babel-loader'
                }]
            }]

    },
    context: __dirname,
    devtool: "source-map",
    target: "web",
    resolve: {
        // options for resolving module requests
        // (does not apply to resolving to loaders)
        modules: [
            "node_modules",
            path.resolve(__dirname, "node_modules")
        ],
        // directories where to look for modules
        extensions: [".js", ".json", ".jsx", ".css"],
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'template/_layout.html'
        })
    ],
    devServer: {
        contentBase: path.join(__dirname, "build"),
        compress: true,
        port: 9000
    }

};
複製代碼

gulp

const gulp = require('gulp');
const eslint = require('gulp-eslint');
 
gulp.task('lint', () => {
    // ESLint ignores files with "node_modules" paths. 
    // So, it's best to have gulp ignore the directory as well. 
    // Also, Be sure to return the stream from the task; 
    // Otherwise, the task may end before the stream has finished. 
    return gulp.src(['**/*.js','!node_modules/**'])
        // eslint() attaches the lint output to the "eslint" property 
        // of the file object so it can be used by other modules. 
        .pipe(eslint())
        // eslint.format() outputs the lint results to the console. 
        // Alternatively use eslint.formatEach() (see Docs). 
        .pipe(eslint.format())
        // To have the process exit with an error code (1) on 
        // lint error, return the stream and pipe to failAfterError last. 
        .pipe(eslint.failAfterError());
});
 
gulp.task('default', ['lint'], function () {
    // This will only run if the lint task is successful... 
});
複製代碼

grunt

require('load-grunt-tasks')(grunt); // npm install --save-dev load-grunt-tasks 
 
grunt.initConfig({
    eslint: {
        target: ['file.js']
    }
});
 
grunt.registerTask('default', ['eslint']);
複製代碼

DEMO

CLI_DEMO

helloworld

echo  Hello World
複製代碼

ESlint(主要演示npm命令)

npm init //https://github.com/advence-liz/nodecmd/blob/master/

npm install

node index.js

package.json

{
  "name": "eslint-demo",
  "version": "1.0.0",
  "description": "a demo for eslint",
  "main": "index.js",
  "scripts": {
    "test": "npm run test"
  },
  "author": "liz",
  "license": "ISC",
  "dependencies": {
    "eslint": "^3.19.0"
  }
}
複製代碼

index.js

"use strict";
var CLIEngine = require("eslint").CLIEngine;

var cli = new CLIEngine({
    envs: ["browser", "mocha"],
    useEslintrc: false,
    rules: {
        semi: 2
    }
});

// lint the supplied text and optionally set
// a filename that is displayed in the report
var report = cli.executeOnText("test.js");
console.dir(report);
複製代碼

run webpack

run webpack-dev-server

webpack NODEAPI

js

const webpack = require("webpack");
//const pkg = require("../package");
const webpack_config= require("../webpack.dev.js")

webpack(webpack_config, (err, stats) => {
    console.log(stats.toString());
// if (err || stats.hasErrors()) {
// // 在這裏處理錯誤
// }
  // 處理完成
});
複製代碼

webpack.config

//var webpack = require('webpack');
var path = require("path"),
    HtmlWebpackPlugin = require('html-webpack-plugin');


module.exports = {
    entry: {
        bundle: "./src/hello.js",
        // react:"./src/react.js",
        index:"./webpack_demo/index.js"
    },
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: "[name].js"

    },
    module: {
        rules: [
            // {
            // test: /\.js$/,
            // enforce: "pre",
            // loader: "eslint-loader"
            // },
            {
                test: /\.js$/,
                exclude: /(node_modules)/,
                use: [{
                    loader: 'babel-loader'
                }]
            }]

    },
    context: __dirname,
    devtool: "source-map",
    target: "web",
    resolve: {
        // options for resolving module requests
        // (does not apply to resolving to loaders)
        modules: [
            "node_modules",
            path.resolve(__dirname, "node_modules")
        ],
        // directories where to look for modules
        extensions: [".js", ".json", ".jsx", ".css"],
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'template/_layout.html'
        })
    ],
    devServer: {
        contentBase: path.join(__dirname, "build"),
        compress: true,
        port: 9000
    }

};
複製代碼

運行展現

HtmlWebpackPlugin

_layout.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="http://cdn.bootcss.com/react/15.4.2/react.js"></script>
    <script src="http://cdn.bootcss.com/react/15.4.2/react-dom.js"></script>
    <title>React App</title>
  </head>
  <body>
    <div id="root"></div>
     <jspath>
  </body>
</html>
複製代碼

template.js

const fs=require("fs");
const path= require("path");
/** * 此處readFile&writeFile 沒有使用相對路徑,由於若是是相對路徑,是相對於當前進程所在的路徑(process.cmd()),而不是相對於當前腳本所在的路徑。 */
var fileName= path.resolve(__dirname,'_layout.html');
var distPath = path.resolve(__dirname,'index.html');
var template = fs.readFileSync(fileName, 'utf8');

template = template.toString().replace(/<jspath>/,`<script src="bundle.js"></script>`);

fs.writeFile(distPath,template,(err) => {
  if (err) throw err;
  console.log('It\'s saved!');
});
複製代碼

index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="http://cdn.bootcss.com/react/15.4.2/react.js"></script>
    <script src="http://cdn.bootcss.com/react/15.4.2/react-dom.js"></script>
    <title>React App</title>
  </head>
  <body>
    <div id="root"></div>
     <script src="bundle.js"></script>
  </body>
</html>
複製代碼

廢稿

javascript

1995年5月,Brendan Eich只用了10天,就設計完成了這種語言的初版。它是一個大雜燴,語法有多個來源:

基本語法:借鑑C語言和Java語言。 數據結構:借鑑Java語言,包括將值分紅原始值和對象兩大類。 函數的用法:借鑑Scheme語言和Awk語言,將函數看成第一等公民,並引入閉包。 原型繼承模型:借鑑Self語言(Smalltalk的一種變種)。 正則表達式:借鑑Perl語言。 字符串和數組處理:借鑑Python語言。 爲了保持簡單,這種腳本語言缺乏一些關鍵的功能,好比塊級做用域、模塊、子類型(subtyping)等等,可是能夠利用現有功能找出解決辦法。這種功能的不足,直接致使了後來JavaScript的一個顯著特色:對於其餘語言,你須要學習語言的各類功能,而對於JavaScript,你經常須要學習各類解決問題的模式。並且因爲來源多樣,從一開始就註定,JavaScript的編程風格是函數式編程和麪向對象編程的一種混合體。

first-class

一般,編程語言會限制操做計算元素的途徑。帶有最少限制的元素被稱爲具備一等地位。一些一等元素的「權利和特權」是:

  • 它們能夠綁定到名稱。
  • 它們能夠做爲參數向函數傳遞。
  • 它們能夠做爲函數的返回值返回。
  • 它們能夠包含在好素具結構中。

ES6 的模塊自動採用嚴格模式,無論你有沒有在模塊頭部加上"use strict"

  • 變量必須聲明後再使用
  • 函數的參數不能有同名屬性,不然報錯
  • 不能使用with語句
  • 不能對只讀屬性賦值,不然報錯
  • 不能使用前綴0表示八進制數,不然報錯
  • 不能刪除不可刪除的屬性,不然報錯
  • 不能刪除變量delete prop,會報錯,只能刪除屬性delete global[prop]
  • eval不會在它的外層做用域引入變量
  • eval和arguments不能被從新賦值
  • arguments不會自動反映函數參數的變化
  • 不能使用arguments.callee
  • 不能使用arguments.caller
  • 禁止this指向全局對象
  • 不能使用fn.caller和fn.arguments獲取函數調用的堆棧
  • 增長了保留字(好比protected、static和interface)
相關文章
相關標籤/搜索