1.事先我們要創(chuàng)建一個文件夾,叫stage
2.在文件夾里創(chuàng)建一個read.me文件在文件里寫上對文件的描述
一個react的腳手架
# main functionalities
- npm scripts [dev product deploy]
- babel[ES6 ES5]
- webpack [圖片、CSS、js等處理]
- jest[單元測試]
# file structure
|- src
|- |- app
|- |- components
|- |- global
|- |- |- reset.css
3.好了 , 然后接下來我們git init一下將其用git來管理,順便按照上面的描述創(chuàng)建文件夾如圖

4.然后接下來我們先要下載babel轉(zhuǎn)譯工具,先touch .babelrc創(chuàng)建一個.babelrc文件,接著npm init創(chuàng)建一個package.json,將scripts里面的內(nèi)容改一下,改成
"scripts": {
"dev": "echo \"hello dev\"",
"prod": "echo \"hello prod\""
}
然后在git bash里輸入npm run dev 看看會出現(xiàn)什么,如果出現(xiàn)hello dev說明沒問題。
5.然后我們要來下載babel依賴了,我們一個個來裝,首先我們要裝es6轉(zhuǎn)譯的,還有jsx語法轉(zhuǎn)譯的。第一步先在之前創(chuàng)建的.babelrc文件里輸入
{
"presets": [
"stage-0",
"es2015",
"react"
]
}
然后在git bash里輸入
$ npm install babel-preset-stage-0 babel-preset-es2015 babel-preset-react --verbose --save-dev
下載完依賴以后,我們就可以嘗試轉(zhuǎn)譯es67語法了,在scripts里面增加
"babel": "babel src/app -d dist"
然后npm運行npm run babel將app里面的js文件轉(zhuǎn)化為es5語法,當(dāng)然必須先在app里創(chuàng)建一個.js文件并輸入依稀es67語法才能轉(zhuǎn)譯成功。
6.我們還需要用webpack來處理我們的js.css.圖片等資源,所以我們創(chuàng)建一個webpack文件夾,為什么需要一個文件夾而不是一個webpack文件呢,因為我們需要適配多種環(huán)境,生產(chǎn)環(huán)境,線上環(huán)境等,所以需要多個webpack文件。接著在webpack文件夾里創(chuàng)建三個文件,分別是
base.config.js
dev.config.js
prod.config.js
然后安裝webpack,
$ npm i webpack --save-dev
7.進(jìn)到base.config.js里面,開始寫一個基本的配置文件
const path = require('path') //path是node.js自帶的路徑工具
module.exports = {
entry: {
sale: "./sale.js"
},
output: {
path: path.resolve(process.cwd(), "dist"), //path.resolve(process.cwd(),) 指當(dāng)前node啟動目錄
filename: "[name].js" //輸出文件name
},
module: {
rules: [
{
test: /\.jsx?$/, //相應(yīng)的文件
loader: 'babel-loader' //處理的插件
},
{
test: /\.css$/,
loader: 'css-loader'
},
{
test: /\.scss$/,
loader: 'sass-loader'
},
{
test: /\.less/,
loader: 'less-loader'
},
{
test: /\.(.png|jpg|jpeg|gif|woff|woff2|ttf|eot|svg|swf)$/,
loader: "file-loader"
}
]
},
}
然后安裝相應(yīng)的依賴
$ npm i babel-loader css-loader less-loader sass-loader file-loader --save-dev --verbose
安裝好之后呢,我們先測試一下代碼到底能不能work,將package.json里的scripts里的dev改成
"dev": "webpack --config webpack/base.config.js"
然后
npm run dev
跑完之后你會發(fā)現(xiàn)它會報錯,報錯內(nèi)容是cant resolve sale.js,找不到sale.js文件,因為webpack entry入口的啟動上下文就是node.js的啟動上下文,所以要加上相應(yīng)路徑,將entry改為
entry: {
sale: "./src/app/sale.js"
}
然后重新npm run dev你會發(fā)現(xiàn)dist里多了一個sale.js的文件,轉(zhuǎn)譯成功。
不過如果每個文件都加個前綴會很麻煩,所以我們手動配置一下webpack的編譯上下文,在 base.config.js里加上
context: path.resolve(process.cwd(), "src/app")
然后把我們的entry改成
entry: {
sale: "./sale.js"
}
也可以跑成功了。
不過我們的入口文件可能會比較多,所以我們把入口文件也分離出來單獨放在一個文件里,在webpack文件夾里重新創(chuàng)建一個entry.js。
entry.js
module.exports = {
sale: "./sale.js"
}
base.config.js
const entry = require('./entry');
module.exports = {
entry: entry,
}
我們可以在app文件夾里再創(chuàng)建一個list.js,里面我們可以隨便寫
list.js
const b = "aaaa"
console.log(b)
然后改一下entry.js
entry.js
module.exports = {
sale: "./sale.js",
list: "./list.js"
}
這樣我們不用動base.config.js就可以增加文件了
8.不過前端不僅有js還有css等。那么這個css文件怎么進(jìn)入我們的項目呢。我們先在app文件夾下新建一個sale.css文件,隨便輸入點內(nèi)容
sale.css
.a {
color: yellow;
}
同時手動引入一下css文件
sale.js
import "./sale.css"
let a = 1;
console.log(a)
然后我們跑一下npm run dev 發(fā)現(xiàn)能成功跑起來,css文件就成功引入了,
不過我們發(fā)現(xiàn)每次改代碼都要重新跑一遍dev,這個太麻煩,我們再用webpack的watch功能
在base.config.js文件里加上
watch: true,
然后重新跑一遍,然后我們會發(fā)現(xiàn),我們改代碼他就會自己重新刷新而不用重新跑npm了。(不過配置文件更改還是要重新跑的)
然后我們查看一下dist里面的文件,發(fā)現(xiàn)里面只有l(wèi)ist.js和sale.js兩個文件,然后看sale.js里面的代碼,

發(fā)現(xiàn).a {color: yellow}竟然在js文件里面,可是我們要的是css文件獨立出來啊,那么我們需要怎么做呢。
9.我們再base.config.js里面只告訴了用什么插件處理css,沒有告訴它把文件拿出來。這個時候我們要安裝一個插件
$ npm install --save-dev extract-text-webpack-plugin
安裝完之后呢,我們可以看看這個插件是怎么用的,可以看下面這個網(wǎng)站
https://github.com/webpack-contrib/extract-text-webpack-plugin
看上面的usage,然后經(jīng)過更改,我們的base.config.js變成了這樣
const path = require('path');
const entry = require('./entry');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
context: path.resolve(process.cwd(), "src/app"),
entry: entry,
watch: true,
output: {
path: path.resolve(process.cwd(), "dist"),
filename: "[name].js"
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader'
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
//resolve-url-loader may be chained before sass-loader if necessary
use: ['css-loader', 'sass-loader']
})
},
{
test: /\.less/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
//resolve-url-loader may be chained before sass-loader if necessary
use: ['css-loader', 'less-loader']
})
},
{
test: /\.(.png|jpg|jpeg|gif|woff|woff2|ttf|eot|svg|swf)$/,
loader: "file-loader?name=[name]_[sha512:hash:base64:7].[ext]"
}
]
},
plugins: [
new ExtractTextPlugin("style.css"),
]
}
寫好配置后我們再安裝一下,style.loader
$ npm install style-loader --save-dev
然后跑一下項目,然后一個基本配置項目成功了。我們可以寫個less或sass文件簡單測試一下。
10.接下來,我們要處理我們的圖片文件。首先在src文件夾下創(chuàng)建一個img文件夾,存放圖片??梢詮木W(wǎng)上隨便下一張圖片放進(jìn)去。有了圖片我們就可以測試一下我們的項目能不能處理圖片。打開剛剛簡單寫的less文件
sale.less
.a {
color: yellow;
.b {
color: red;
}
.c {
background: url('../img/2cun.jpg');
}
}
然后你會發(fā)現(xiàn)dist里面會有一張和你之前放進(jìn)img文件夾里一樣的圖片。
11.不過隨著文件的增加,我們不能把所有的css、圖片都放在同一個文件夾里,我們必須把他們單獨分開。把css和圖片單獨放在文件夾里。改一下file-loader和plugins的配置
base.config.js
test: /\.(.png|jpg|jpeg|gif|woff|woff2|ttf|eot|svg|swf)$/,
loader: "file-loader",
options: {
name: 'assets/[name]_[sha512:hash:base64:7].[ext]'
}
plugins: [
new ExtractTextPlugin("css/[name].css"),
]
12.我們發(fā)現(xiàn)配置里面并沒有html,接下來我們要引入html文件,在那之前,我們先下載一個工具——webpack-dev-server
首先我們先下載下來
$ npm i webpack-dev-server --save-dev
然后改一下package.json的dev命令
"scripts": {
"dev": "webpack-dev-server --config webpack/base.config.js",
"prod": "echo \"hello prod\"",
"babel": "babel src/app -d dist"
},
然后我們跑npm run dev就會產(chǎn)生一個8080端口。這個時候我們再建一個html文件就完事了。不過如果想改變它的輸出端口號,我們可以對base.config.js文件進(jìn)行編輯
devServer: {
contentBase: path.resolve(process.cwd(), "指定的文件地址"),
compress: true,
port: 9000
}
為了建立html,我們要再引入一個插件webpack-html-plugin
$ npm install html-webpack-plugin --save-dev
引入后參照文檔
https://github.com/jantimon/html-webpack-plugin
將文檔里的內(nèi)容拷貝進(jìn)來
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpackConfig = {
entry: 'index.js',
output: {
path: __dirname + '/dist',
filename: 'index_bundle.js'
},
plugins: [new HtmlWebpackPlugin()]
};
就是在我們的base.config.js里面加入這一行代碼
const HtmlWebpackPlugin = require('html-webpack-plugin');
然后改一下plugins
plugins: [
new ExtractTextPlugin("css/[name].css"),
new HtmlWebpackPlugin()
]
然后再跑dev,發(fā)現(xiàn)我們打開了一個空的html,里面引入了sale.js和sale.css。不過我們在真的項目里面并不能這么做。
13.我們在src文件里新建一個base文件夾,創(chuàng)建一個webpack.template.html模板代碼,編輯它
webpack.template.html
<html>
<head>
<title><%=htmlWebpackPlugin.options.title%></title>
</head>
<body>
<div id="root"></div>
</body>
</html>
然后配置這么改
plugins: [
new ExtractTextPlugin("css/[name].css"),
new HtmlWebpackPlugin({
title: 'sale',
template: path.resolve(
process.cwd(),
'src/base/webpack.template.html'),
filename: 'sale.html',
chunks: ['sale'] //sale.html引入的css和js文件資源
})
]
測試一下,npm run dev就會打開端口相應(yīng)的資源。
14.測試完成接下來我們繼續(xù),在stage文件夾里新建一個sample文件夾,里面新建sale.html。同時編輯一下
sale.html
<html>
<head>
<title>sale</title>
<link href="/dist/sale.css" ref="stylesheet">
</head>
<body>
<div id="root"></div>
<script src="/dist/sale.js">
</body>
</html>
然后改一下base.config.js里的derServer和output
output: {
publicPath: "/dist", //加了一個publicPath,webpack-dev-server會去讀取相應(yīng)路徑下面的文件,所以上面可以得到sale.js等文件
path: path.resolve(process.cwd(), "dist"),
filename: "[name].js"
},
devServer: {
contentBase: path.resolve(process.cwd(), "sample"),
compress: true,
port: 9000
}
然后npm run dev就能得到一個html頁面了
15.接下來我們就要開始引入框架了,這里我們先引入的是react,直接下載
$ npm install react --save
$ npm install react-dom --save
同時在base.config.js里加個resolve
resolve: {
extensions: [".js", ".jsx", ".json"]
},
編輯sale.js
import './sale.less'
import React from 'react';
import ReactDom from 'react-dom'
const node = document.getElementById('root')
ReactDom.render("hello world", node);
let a = "2";
console.log(a)
這樣一個小型的腳手架就完成了
16.但是想想這個腳手架還缺了點什么,缺什么呢,還缺單元測試?。?br> 我們通過下載jest工具來幫我們完成單元測試。
$ npm install --save-dev jest
然后在package.json里增加一條:
scripts: {
"text": "jest"
}
接著在src下面創(chuàng)建一個 service文件夾,在里面創(chuàng)建一個 calculate.js,再創(chuàng)建一個calculate.text.js做測試
calculate.js
function calculate(a, b) {
return a + b;
}
module.exports = calculate;
calculate.text.js
const calculate = require('./calculate');
test('adds 1 + 2 to equal 3', () => {
expect(calculate(1, 2)).toBe(3);
});
然后npm run test開始測試,如果是pass,則運行成功 代碼沒問題
17.接下來我們要配置生產(chǎn)環(huán)境下的webpack配置,用webpack-gulify打包壓縮
npm i -D uglifyjs-webpack-plugin
然后編輯prod.webpack.js
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const baseWebpackPlugin = require('./base.config.js');
const plugins = baseWebpackPlugin.plugins;
const newPlugins = plugins.concat([new UglifyJsPlugin()]);
module.exports = Object.assign({},
baseWebpackPlugin,
{
plugins: newPlugins
}
)
package.json
"scripts": {
"prod": "webpack --config webpack/prod.config.js --optimize-minimize",
},
既然生產(chǎn)環(huán)境分離出來了,那dev環(huán)境也分離一下將base.config.js里的
watch: true,
devServer: {
contentBase: path.resolve(process.cwd(),"sample"),
compress: true,
port: 9000
}
轉(zhuǎn)移到dev.config.js里
const baseWebpackConfig = require('./base.config.js');
const devWebpackPartialConfig = {
watch: true,
devServer: {
contentBase: path.resolve(process.cwd(),"sample"),
compress: true,
port: 9000
}
}
module.exports = Object.assign({},
baseWebpackConfig,
devWebpackPartialConfig
)
18.好了 到現(xiàn)在,一個基本的腳手架就完成了,如果需要要vue,就直接下載就行了。