事例一:咱們在使用react的時候,會用create-react-app
命令下載一個react的模板,而後開始在裏面實現各類功能。css
事例二:前幾個月的時候,我偶然發現飛冰官網,瀏覽後以爲不錯,並在其上面下載了幾個模板。html
那咱們可能好奇兩件事情:前端
本文將按照我本身的一個想法、以react
模板樣式爲基準,就這兩個話題展開敘述。vue
├─ build // webpack配置目錄
│ ├─ webpack.base.js // webpack共有配置
│ ├─ webpack.dev.js // webpack開發環境配置
│ └─ webpack.prod.js // webpack生產環境配置
├─ public // 模板存放目錄
│ ├─ favicon.ico // 網站圖標
│ └─ index.html // 模板html文件
├─ src // 項目
│ ├─ common // 共有方法
│ ├─ compoents // 自封裝組件
│ ├─ layouts // 佈局組件
│ ├─ pages // 頁面
│ ├─ index.js // 項目入口
│ ├─ App.css // css樣式
│ ├─ logo.svg // 首頁logo
│ └─ App.jsx
├─ .babelrc // babel配置文件
├─ .browerslistrc // 配置瀏覽器的兼容性範圍
├─ .gitignore // 忽略上傳文件
├─ package.json
├─ README.md // 工程搭建文檔說明
複製代碼
首先,咱們要建立一個空目錄,而後初始化項目 npm init -y
執行完命令,咱們會在目錄中看見一個package.json
文件。 node
咱們知道,不管是項目的啓動仍是打包,它的命令是從package.json
文件中本身定義的。在建立的模板中,有start
命令-啓動react
,有build
-將react
項目打包,目前咱們只配置這兩個命令以及開發環境下的打包、生產環境下啓動服務命令。react
找到pakage.json
文件中的scripts
,像這樣配置webpack
"scripts": {
"start": "webpack-dev-server --env.development --config ./build/webpack.base.js", // 開發環境啓動服務,
"dev":"webpack --env.development --config ./build/webpack.base.js", // 開發環境打包代碼
"build": "webpack --env.production --config ./build/webpack.base.js", // 生產環境打包代碼
"build:server": "webpack-dev-server --env.production --config ./build/webpack.base.js" // 生產環境啓動服務
},
複製代碼
這樣,咱們完成了基礎的配置,可是,咱們會思考:不一樣的平臺(Mac
和Windows
)是否是會出現設置環境變量不同的問題?基於這個問題,咱們找到了cross-env
插件,那咱們應該如何將上面配置好的scripts
改進呢?git
"scripts": {
"start": "cross-env NODE_ENV=development webpack-dev-server --config ./build/webpack.base.js",
"dev":"cross-env NODE_ENV=development webpack --config ./build/webpack.base.js",
"build": "cross-env NODE_ENV=production webpack --config ./build/webpack.base.js",
"build:server": "cross-env NODE_ENV=production webpack-dev-server --config ./build/webpack.base.js"
},
複製代碼
配置好之後,下一步,咱們就開始配置webpackgithub
const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
const dev = require('./webpack.dev');
const prod = require('./webpack.prod');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const isDev = process.env.NODE_ENV === 'development';
const base = {
entry: path.resolve(__dirname, '../src/index.js'), // 入口
module: {
rules: [{ // 對.js、.jsx的處理
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: 'babel-loader'
}, { // 對.css的處理
test: /\.css$/,
use: [
!isDev && MiniCssExtractPlugin.loader, // 生產環境下樣式抽離
isDev && 'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1 // 引入的文件調用後面的loader處理
}
},
{ // 智能添加樣式前綴
loader: "postcss-loader",
options:{
plugins:[require('autoprefixer')]
}
},
].filter(Boolean)
}, {
test: /\.scss$/, // css預處理器scss的處理
use: [
!isDev && MiniCssExtractPlugin.loader, // 生產環境下抽離樣式
isDev && 'style-loader',
"css-loader",
"sass-loader"
].filter(Boolean)
}, {
test: /\.less$/, // css預處理器less的處理
use: "less-loader",
}, {
test: /\.stylus$/, // css預處理器stylus的處理
use: "stylus-loader",
}, {
test: /\.(jpe?g|png|svg|gif)$/, // 對圖片的處理
loader: "file-loader",
options: {
name: "image/[contentHash].[ext]"
},
}, {
test: /\.(woff|ttf|eot|otf|ico)$/, // 對字體圖標的處理
loader: "file-loader",
options: {
name: "image/[name].[ext]"
},
}]
},
output: { // 出口
filename: 'scripts/[name].bundle.js',
path: path.resolve(__dirname, '../dist')
},
resolve: { // 引入js、jsx文件時,無需添加後綴
extensions: ['.js', '.jsx'],
},
plugins: [
!isDev && new MiniCssExtractPlugin({ // css樣式抽離
filename: 'css/[name].[contentHash].css'
}),
new HtmlWebpackPlugin({ // 配置入口html
filename: 'index.html',
template: path.resolve(__dirname, '../public/index.html'),
hash: true,
inject: true,
favicon: path.resolve(__dirname, '../public/favicon.ico'),
minify: !isDev && {
removeAttributeQuotes: true, // 去掉屬性雙引號
collapseWhitespace: true, // 將html文件摺疊成一行
}
}),
new webpack.HotModuleReplacementPlugin(),
].filter(Boolean),
devServer: { // 配置服務
hot:true, // 熱更新
port: 3000, // 端口號
compress: true, // 提高頁面返回速度
open: true, // 啓動服務後自動啓動瀏覽器
contentBase: path.resolve(__dirname, '../dist'), // webpack啓動服務會在dist目錄下
}
}
module.exports = () => { // 根據環境合併webpack
if (isDev) {
return merge(base, dev);
} else {
return merge(base, prod);
}
}
複製代碼
module.exports = {
mode: 'development',
}
複製代碼
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
mode: 'production',
plugins: [
new CleanWebpackPlugin(), // 打包前清空dist目錄
new UglifyJsPlugin({ // 打包後自動去除debugger、console等
uglifyOptions: {
compress: {
drop_debugger: true,
drop_console: true,
pure_funcs: ['console.log', 'debugger']
}
},
parallel: true
}),
],
}
複製代碼
咱們能夠優化咱們的webpack
配置~web
關於webpack
的配置優化,後續,會單獨寫一個文章~
咱們都用過vue-cli
、create-react-app
等命令下載一個初始的vue
、react
模板,這裏我要寫一個屬於本身的cli
下載屬於本身的模板(手動狗頭)~
個人cli
在npm
上的名字叫react-demo-cli
,下載模板的命令是create-react-cli download
因此,在使用的時候,先輸入命令 npm install react-demo-cli -g
而後 create-react-cli download
就能夠啦~
效果是這樣嬸滴
這一篇文章的核心簡單來講有兩條
webpack
cli
只要這兩件事情搞定了,問題就不難了這裏,主要說了從零搭建本身的react框架的思路、方法,效果和create-react-app
等比起來,仍是差不少。因此,我會不斷優化本身和本身的代碼~
還有:
cli
,只有使用方法,後續會有專門的文章講解如何搭建一個本身的cli
。這裏還要感謝圈圈的圈
的cli代碼講解~webpack
,我使用了webpack-dev-server
來啓動服務,這樣啓動的服務在控制檯打印了不少東西,因此後續會改成本身編寫腳本的方式~下面,是cli
和react-template
的github
地址
上面的文章若有不對之處,還請你們指點出來~咱們共同進步~
而後,分享一下個人公衆號「web前端日記」的二維碼,歡迎前來你們關注~