摘要:那我們有沒有辦法不刷新頁面又能看到代碼的更新呢其實很簡單,因為已經內置了這樣的功能,我們只要配置下的注意到上面的代碼,我們增加了,讓開發環境有了熱更新的能力。
作者:Nicolas (滬江Web前端)
本文為原創文章,轉載請注明作者及出處
本文的 webpack 代碼示例根據 webpack 2.7.0 編寫,并在 Mac 上正常運行。
去年一篇《在 2016 年學 JavaScript 是一種什么樣的體驗?》嚇壞了很多想要入行新同學和入行很久的老司機,感覺一下子前端世界已經看不懂了,做個頁面要那么麻煩?當然如果你只是想要一個簡單的靜態頁面,這么玩兒就是殺雞用牛刀了。但如果你準備開發一個 Web App,之后會不斷的迭代,有一個舒適的開發環境是及其重要的,那么底怎么樣的環境才會是舒適愉悅的呢?
比如這樣的一個環境:資源依賴可以安裝并模塊化引用、可以使用很酷的 ES6 語法、可以使用 SASS 預處理器寫 CSS、代碼可實時更新而不用一遍遍的手動刷新頁面,這樣的開發環境你會不會覺得很爽!好,我們這就來配置一個這樣的環境!
基礎環境首先,你需要一個 Node.js,然后 NPM 也會隨著 Node.js 一起裝上。
什么是 NPM ?簡單的說 NPM 是用來下載安裝 Node.js 的第三方工具包的一個管理器。當然,現在也可以安裝瀏覽器中使用的包。提到包管理器,就不得不說下 Bower,Bower 之前一直是前端庫管理工具,一開始 NPM 只能發布和安裝 Node.js 的包,所以 Bower 盛行一時,隨著 CommonJS 的普及,以及 UMD 規范的出現,讓 NPM 安裝前端瀏覽器 js 包成為了可能,隨著 NPM 生態的成熟,Bower 也就慢慢被人淡忘了~
Node.js 安裝完成后,可以執行以下命令驗證安裝是否成功:
$ node -v v6.11.0 $ npm -v 3.10.10
別急,Node.js 的部分還沒完,國內通過 NPM 的官方源安裝依賴好像很慢,動不動就要等上半天,如何解決?我們可以裝一個 nrm!nrm 是 npm registry 管理工具,可以自由切換 npm registry,然后命令行使用時依然是 npm ,國內有很多 npm 的鏡像,比如淘寶的 cnpm ,然而很多公司都架設了自己的私庫。什么是私庫?私庫就是只能在公司內網訪問,不能發布到 npm 共享平臺的 npm 包,比如我們大公司私庫的 registry 的名稱就是 hnpm。不細說了,我們先裝一個試試:
$ npm install -g nrm
然后根據官方教程我們先切一個國內的 registry,比如大淘寶的:
$ nrm use cnpm
然后用 NPM 隨便安裝個什么,看看速度如何?是不是很快^_^
等等,Node.js 還有。有的開發依賴包是有 Node.js 版本依賴的,我們知道 Node.js 不同大版本的功能還是差別很大的,但我們又不會一遍遍的卸載安裝吧?感覺好蠢!好吧,我們當然可以裝一個nvm,nvm?好像和 nrm 很像!nvm 是 Node.js 的版本管理工具,可以在多個終端切換和運行不同的 Node.js 版本,可以到這里參考具體的安裝教程。不過 nvm 在 windows 下不能使用,沒關系,這里還有幾個替代工具:nvm-window,gnvm 供你選擇。
同樣,我們執行下命令驗證安裝成果:
$ nvm --version 0.33.0項目初始化
有了上面的工具我們就可以開始創建一個項目了,我們執行以下命令來開始一個項目:
mkdir my-app cd my-app npm init
執行 npm init 后你會看到你需要輸入項目的一些信息,完成后回車確認,然后npm會在根目錄下創建一個叫 package.json 的文件,你之后通過 --save 或者 --save-dev 安裝的依賴包都會出現在這個文件里。
先不管那么多,我們在根目錄下創建一個 src 目錄,然后在 src 下創建index.js、index.html……,好吧,你可以按照下面的結構新建文件:
. ├── package.json └── src ├── index.css ├── index.html └── index.js
在以下文件中輸入代碼:
index.js:
var el = document.createElement("div"), text = document.createTextNode("My App"); el.appendChild(text); document.body.appendChild(el);
index.html:
My App
我們要想辦法讓這個頁面跑起來,what??? 就這么簡單?,把js引入 index.html 不就完事兒了嘛?當然沒那么簡單,我們可是要搞高大上的東西的呢!
哈~跑題了,我們繼續。
首先我們要裝一個叫 webpack 的東西,它是一個模塊打包器,也就是我們俗稱的構建工具,之前的那些 Grunt,Gulp 也都是構建工具,但是這年頭流行 webpack 了!開個玩笑,webpack 的可擴展性和可插件化,以及把任何文件都視為模塊的概念得到了前端社區的一致推崇,而且在打包效率和按需分割文件上都是其他幾個構建工具無法相比較的,當然 webpack 的配置太靈活,官方文檔寫的太太太難看懂,也導致了很多初學者無從下手。
接下來我們就來配下這個神奇的工具吧。
自動構建我們先安裝下 webpack:
npm install --save-dev webpack
然后在根目錄下新建一個 webpack.config.js 文件,輸入以下代碼:
let path = require("path"); module.exports = { entry: { app: path.resolve(__dirname, "src", "index.js") }, output: { filename: "[name].js", path: path.resolve(__dirname, "dist") } };
但要想在瀏覽器中訪問還得有個本地服務器,好在 webpack 都幫我們想到了,我們可以裝一個webpack-dev-server:
npm install --save-dev webpack-dev-server
我們在 package.json 中增加個 npm scripts:
"scripts": { "start": "webpack-dev-server --port 3003" },
ok!我們執行下 npm start,在瀏覽器中訪問:http://localhost:3003。哎?好像哪里不對!是的,你得告訴 webpack,你的 bundle(打包后的 js)要插入到哪個 html 模板,前面說過,webpack 是插件化的,它把很多功能開放給了第三方來實現,他只是來負責拼裝的,好,現在我們需要安裝一個 html-webpack-plugin 插件:
npm install --save-dev html-webpack-plugin
修改下 webpack-config.js:
let HtmlWebpackPlugin = require("html-webpack-plugin"), path = require("path"); module.exports = { entry: { ... }, ... plugins: [ new HtmlWebpackPlugin({ template: path.resolve(__dirname, "src", "index.html") }) ] }
再次執行 npm start,頁面可以正常訪問了。
但是,這樣似乎有點 low,我們新增一個文件 utils.js,搞點es6語法:
. ├── package.json └── src ├── index.css ├── index.html ├── index.js +?? └── utils +?? └── utils.js
utils.js:
export function wordsToSentence(...words) { return words.join(" "); }
修改 index.js
+ import { wordsToSentence } from "./utils/utils"; let el = document.createElement("div"), - text = document.createTextNode("My App"); + text = document.createTextNode( + wordsToSentence("Welcome", "to", "my", "app!") + ); el.appendChild(text); document.body.appendChild(el);
刷新頁面后好像也沒什么異常(你肯定用了 chrome 吧!),仔細看控制臺的 source 的 app.js(你的 bundle)的代碼片段:
"use strict"; /* harmony export (immutable) */ __webpack_exports__["a"] = wordsToSentence; function wordsToSentence(...words) { return words.join(" "); }
值得注意的是,使用 ES6 時需要考慮那些沒有支持 ES6 的舊瀏覽器,雖然在 chrome 或者其他高級瀏覽器中沒有出現問題,但不能保證在其他瀏覽器中能正常運行。為了萬無一失,我們需要將 ES6 轉換為 ES5,也就是js代碼轉換器,這類工具當今世界就屬 Babel 最牛逼了:
npm install --save-dev babel-loader babel-core
稍等,裝了 Babel 還沒法用,還得搞個 presets:
npm install --save-dev babel-preset-env
在根目錄下新建個 .babelrc,輸入配置:
{ "presets": ["env"] }
修改 webpack.config.js,增加 babel 的支持:
... module.exports = { ... module: { rules: [ { test: /.js$/, loader: "babel-loader", include: path.resolve(__dirname, "src") } ] }, ... };
執行 npm start,找到控制臺 source 下的 app.js 代碼片段:
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.wordsToSentence = wordsToSentence; function wordsToSentence() { for (var _len = arguments.length, words = Array(_len), _key = 0; _key < _len; _key++) { words[_key] = arguments[_key]; } return words.join(" "); }
已經成功轉換成 ES5 代碼。但是,目前 ES6 Modules 是由 Babel 來轉的,你可以對比前后 2 次的代碼片段的模塊輸出部分。現在,webpack 2 已經內 4 置了 ES6 Modules 的轉換,據說效率和性能比 Babel 高!^_^沒驗證過哦,我們先試試,把 Babel 的模塊轉換關了先:
.babelrc
{ "presets": [ ["env", { "modules": false }] ] }
執行 npm start 再次查看輸出后的 app.js 的代碼片段:
-Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.wordsToSentence = wordsToSentence; +/* harmony export (immutable) */ __webpack_exports__["a"] = wordsToSentence; function wordsToSentence() { ... }
模塊輸出方式又回到了使用 Babel 前的代碼。
js 的環境似乎已經準備就緒,但 css 還沒上場,我們來修改下 index.css:
#app { color: #57af09; }
同時將 css 導入 bundle 入口,并修改下 index.js:
import "./index.css"; import { wordsToSentence } from "./utils/utils"; let el = document.createElement("div"), ... el.id = "app"; ...
有了樣式還不行,webpack 還需要相應的 loader 來處理 css 的模塊:
npm i --save-dev style-loader css-loader
修改下 webpack.config.js:
... module.exports = { ... module: { rules: [ ... { test: /.css$/, loader: ["style-loader", "css-loader"], include: path.resolve(__dirname, "src") } ] }, ... };
執行 npm start,現在可以看到頁面已經有了樣式。但是,我們說過,我們希望使用先進的武器:SASS。我們修改下 index.css:
$app-color: #57af09; #app { color: $app-color; }
再修改下文件后綴:
. ├── package.json └── src - ├── index.css + ├── index.scss ...
修改 index.js 的入口:
-import "./index.css"; +import "./index.scss";
由于文件(模塊)類型變了,我們還需要一個 SASS 的 webpack loader:
npm install --save-dev sass-loader node-sass
再次修改 webpack.config.js:
... module.exports = { ... module: { rules: [ ... { - test: /.css$/, + test: /.scss$/, - loader: ["style-loader", "css-loader"], + loader: ["style-loader", "css-loader", "sass-loader"], include: path.resolve(__dirname, "src") } ] }, ... };
執行 npm start,webpack 編譯沒有報錯,頁面顯示一切正常!
代碼自動更新(熱更新)如果你嘗試修改 index.scss 的樣式,你有沒注意到一個問題:頁面會自動刷新。但有時候我們在開發一個模塊,比如 dialog,刷新會導致你需要反復的在頁面上操作才能看到這個 dialog 的樣式更新。那我們有沒有辦法不刷新頁面又能看到代碼的更新呢?
其實很簡單,因為 webpack-dev-server 已經內置了這樣的功能,我們只要配置下 package.json的 npm scripts:
"scripts": { "start": "webpack-dev-server --hot --inline --port 3003" },
注意到上面的代碼,我們增加了 --hot --inline,讓開發環境有了熱更新的能力。我們重新執行 npm start,然后將你的瀏覽器和編輯器并排放置,然后反復修改 index.scss,你會看到頁面不會刷新,但樣式在自動的推送更新,這就是傳說中的熱更新。
結束語到這里,簡單(簡陋)的、現代化的前端開發環境已經有了基本的雛形,但是,本篇文章不是webpack 的使用指南,也不是 ES6 的語法教程,盡管如此,還是希望你通過本篇文章感受到前端開發在工程化領域的發展帶來的驚喜。
iKcamp原創新書《移動Web前端高效開發實戰》已在亞馬遜、京東、當當開售。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/85135.html
摘要:前端日報精選如何優雅的編寫代碼深入理解內部機制專題之函數組合年月個有趣的和庫最經典的前端面試題之一,你能答出什么幺蛾子中文翻譯深入理解響應式原理掘金譯與和交互掘金箭頭函數使用禁忌技術棧耕耘助力美團點評前端進階之路前端模塊 2017-09-01 前端日報 精選 如何優雅的編寫 JavaScript 代碼深入理解 Node.js Stream 內部機制JavaScript專題之函數組合20...
摘要:馬爾代夫之行重頭戲這一年的工作情況這一年,個人感覺還是做了不少事情,主要集中在我們公司的前端領域,同時也給整個技術團隊不少的建議,引入了不少新的東西和方式,總結起來比較重要的在下面五個方面。 如果想看技術相關的,下拉到后面的重頭戲就是了。 一個活動頁面 在15年末的時候,加入到羅輯思維,剛過來就接手了一個微信朋友圈要傳播的活動頁面,效果頁面大概和當時錘子手機的活動頁面漂亮的不像實力派類...
摘要:老姚淺談怎么學鑒于時不時,有同學私信問我老姚,下同怎么學前端的問題。擼碼聽歌,全局控制。 淺析用 js 解析 xml 的方法 由于項目上需要解析 xml,于是各種百度,然后自己總結了下各個主流瀏覽器解析 xml 的方法,只能是很淺顯的知道他的用法,但是還沒有深層次的研究。 裝 X - 建立自己的斗圖網站庫 之前加過一個斗圖群,看到很多經典的表情,然后就收藏到了 QQ, 迫于本屌絲開不起...
閱讀 1668·2023-04-26 00:30
閱讀 3145·2021-11-25 09:43
閱讀 2868·2021-11-22 14:56
閱讀 3183·2021-11-04 16:15
閱讀 1137·2021-09-07 09:58
閱讀 2014·2019-08-29 13:14
閱讀 3101·2019-08-29 12:55
閱讀 982·2019-08-29 10:57