事例一:咱们在使用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前端日记」的二维码,欢迎前来你们关注~