新建个项目
-
npm init -y
-
npm i webpack@4.43.0 webpack-cli -D
-
项目根目录中创建一个 src文件夹,src文件夹下新建
index.js
和index.html
文件 -
执行npx webpack测试。
-
下载
// html-webpack-plugin的版本要与webpack的版本一致,例如webpack用的是4,那么html-webpack-plugin版本也要是4 // 否则会报错:html-webpack-plugin中 Cannot read property 'tap' of undefined npm i html-webpack-plugin@4.3.0 clean-webpack-plugin -D
-
修改配置
// 创建webpack.config.js文件 const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { entry: { index: './src/index' }, output: { path: path.resolve(__dirname, './dist'), filename: '[name].js' }, mode: 'development', module: { rules: [] }, devtool: 'cheap-source-map', plugins: [ new HtmlWebpackPlugin({ template: './src/index.html', filename: 'index.html', chunks: ['index'] }), new CleanWebpackPlugin() ] }
-
添加样式
css:
// src下新建个styles/index.css body { background-color: pink; } // 下载loader npm i style-loader css-loader -D // 修改webpack.config.js文件中的module module: { rules: [ { test: /\.less$/, use: ['style-loader', 'css-loader'] } ] }
less:
// src下新建个styles/index.less html{ body { display: flex; background-color: pink; } } // index.js中引入less import './styles/index.less'; // 下载less-loader (最新版本不兼容 指定一个版本下载) // less-laoder是webpack沟通less编译器的桥梁 所以我们还需要安装less来转换为css文件 npm install less less-loader@5.0.0 -D // 修改webpack.config.js文件中的module module: { rules: [ { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] } ] }
后处理器postcss
为了使css3语法被更多浏览器所兼容,也就是说给样式⾃动添加前缀。
// 最新版本不兼容 指定一个版本下载
// 不需要安装postcss了,因为之前我们安装css-loader依赖包依赖它,所以就已经安装了
npm i postcss-loader@3.0.0 autoprefixer@9.8.4 -D
// 修改webpack.config.js文件中的module
module: {
rules: [
{
test: /\.less$/,
use: ['style-loader', 'css-loader', "postcss-loader", 'less-loader']
}
]
}
// 新建postcss.config.js文件
module.exports = {
//postcs就是处理css成AST抽象语法树
//如何把这个AST抽象语法树转换成相应的css => postcss插件机制
plugins: [
require("autoprefixer")({
overrideBrowserslist: ["last 3 versions", ">2%"],
// 配置参数 降低浏览器的标准,因为浏览器很多属性已经支持了
// browserslist: package.json中的一个配置字段,浏览器的类型,告诉项目是兼容到哪些浏览器的
// overrideBrowserslist: override是重写、覆盖的意思,这样它的优先级就比browserslist高
// ["last 3 versions", ">2%"]:是 last 2 versions是兼容到浏览器的最后(最新)三个版本,>2%是浏览器在市面上的占有率大于2%的都要兼容到
}),
],
};
静态资源
图片
file-loader
处理静态资源模块。原理是把打包⼊⼝中识别出的资源模块,移动到输出⽬录,并且返回⼀个地址名称。什么时候⽤file-loader呢?场景:就是当我们需要模块,仅仅是从源代码挪移到打包⽬录,不需要对文件的内容进行加工的,就可以使⽤file-loader来处理,txt,md,png,word,pdf, svg,csv,excel等等。
npm i file-loader -D
配置:
{
test: /\.(jpg|png|jpeg)$/,
use: {
loader: 'file-loader',
options: {
// [name]: 之前的图片名字
// [hash:4]: [hash]是本次打包的hash值,[hash:4]是截取4位hash值
// [ext]是之前图片的后缀
name: "[name]_[hash:4].[ext]"
}
}
}
使用:
-
index.html中添加:
<p></p>
-
src下新建个imgs文件夹,放入一张图片
-
index.less中:
p {
background: url('../imgs/1.jpg');
width: 200px;
height: 200px;
}
url-loader
内部使⽤了file-loader,所以可以处理file-loader所有的事情,但是遇到jpg格式的模块,会把该图⽚转换成base64格式字符串,并打包到js⾥。对⼩体积的图⽚⽐较合适,⼤图⽚不合适。
npm i url-loader -D
{
test: /\.(jpg|png|jpeg)$/,
use: {
loader: 'url-loader',
options: {
name: "[name]_[hash:4].[ext]",
outputPath: 'imgs/',
limit: 20480, // ⼩于20480,才转换成base64,可以帮助我们处理小体积的图片,减少http请求
}
}
}
字体font
-
前往阿里iconfont官网,找到对应的图标,下载代码。
-
在项目中新建个fonts文件,找到下载代码中的
iconfont.woff2
文件,,放入fonts文件夹中。 -
在index.less中加入字体的css
例如:
@font-face {
font-family: 'iconfont';
src: url('../fonts/iconfont.woff2') format('woff'),
}
.iconfont {
font-family: "iconfont" !important;
font-size: 24px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
-
在index.html中加入对应的标签
<span class="iconfont"></span>
-
修改配置
{ test: /\.(ttf|woff|woff2|svg)$/, use: { loader: 'file-loader', options: { name: "[name]_[hash:4].[ext]", outputPath: 'fonts/', } } }
-
重新打包
多页面常用打包配置
借助glob来匹配路径。
先安装:
npm i glob -D
在src下新建个views文件夹用于存放我们的页面,然后在里面新建login文件夹,文件夹中新建index.html、index.js文件。如果还有其他页面,只需要保证文件夹内文件名字是index.html、index.js即可。
修改配置文件增加以下代码:
const glob = require('glob');
const setEntryAndPlugin = () => {
const entry = {};
const htmlWebpackPlugins = [];
const entryFiles = glob.sync(path.join(__dirname, './src/views/*/index.js'));
entryFiles.forEach(item => {
const match = item.match(/src\/views\/(.*)\/index.js/);
const pageName = match && match[1];
entry[pageName] = item;
htmlWebpackPlugins.push(new HtmlWebpackPlugin({
template: `./src/views/${pageName}/index.html`,
filename: `${pageName}.html`,
chunks: [pageName]
}))
})
return {
htmlWebpackPlugins,
entry
}
}
const {entry, htmlWebpackPlugins} = setEntryAndPlugin();
module.exports = {
entry: {
index: './src/index',
...entry,
},
xxxxxx,
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
chunks: ['index']
}),
...htmlWebpackPlugins,
new CleanWebpackPlugin()
]
}
请求
下载express和axios以及mock。
npm i express axios mockjs -D
新建个serve/serve.js文件,写上代码:
const express = require('express');
const app = express();
const Mock = require('mockjs');
app.get('/apis/getUser', (req, res) => {
const data = Mock.mock({
'list|1-10': [{
'id|+1': 1,
'name': '@name',
'age|10-40': 1
}],
});
res.send(data);
});
app.listen('3001');
在终端中找到这个文件,执行命令:node serve.js
启动这个服务。
测试:
在页面上打开: http://localhost:3001/apis/getUser查看有无数据。
在index.js中,发送请求:
import axios from 'axios';
axios.get('http://localhost:3001/apis/getUser').then(res => {
console.log(res);
})
然后我们就看到跨域了,因为不同源。
解决方法:使用WebpackDevServer
。用法及注意点:
修改配置:
devServer: {
contentBase: path.resolve(__dirname, '../dist'), // 默认会以根文件夹提供本地服务器,这里指定文件夹(指向静态资源目录)
inline: true, // 自动刷新
hot: true, // 开启热模块替换
historyApiFallback: true, // 在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html
open: true, // 服务启动之后,会自动帮我们打开浏览器窗口
publicPath: '/',
compress: true, // 使用gzip压缩
stats: 'minimal',
port: 8080, // 端口号,默认是8080
proxy: { // 代理
"/apis": {
target: 'http://localhost:3001'
}
}
},
然后请求修改为:
axios.get('/apis/getUser').then(res => {
console.log(res);
})
启动服务器,查看请求。
babel
官⽅⽹站:babeljs.io/
中⽂⽹站:www.babeljs.cn/
Babel是JavaScript编译器,能将ES6代码转换成ES5代码,让我们开发过程中放⼼使⽤JS新特性⽽不⽤担⼼兼容性问题。并且还可以通过插件机制根据需求灵活的扩展。
Babel在执⾏编译的过程中,会从项⽬根⽬录下的 .babelrc JSON⽂件中读取配置。没有该⽂件会从loader的options地⽅读取配置。
安装:
npm i babel-loader @babel/core @babel/preset-env core-js -D
- @babel/preset-env⾥包含了es,6,7,8转es5的转换规则
- babel-loader是webpack 与 babel的通信桥梁,不会做把es6转成es5的⼯作,这部分⼯作需要⽤到@babel/preset-env来做
- env是babel7之后推⾏的预设插件
通过上⾯的⼏步 还不够,默认的Babel只⽀持let等⼀些基础的特性转换,Promise等⼀些还有转换过来,这时候需要借助@babel/polyfill,把es的新特性都装进来,来弥补低版本浏览器中缺失的特性。
npm i @babel/polyfill -D
根目录下新建个.babelrc
文件,把配置项都放入到这个文件中。
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage", // 按需加载:但是不需要import ,全⾃动检测
"corejs": 3 // /新版本需要指定核⼼库版本
}
]
]
}
增加一个rules:
{
test: /\.(js|jsx)$/, // js或者jsx文件都可以
exclude: /node_modules/,
use: {
loader: "babel-loader",
}
}
测试: index.js中
new Promise((resolve, reject) => {
axios.get('/apis/getUser').then(res => {
resolve(res);
}).catch(err => {
reject(err);
})
}).then(({ data: { list } }) => {
console.log(list);
})
配置react
安装:
npm i react react-dom -D
// babel与react转换的插件
npm i @babel/preset-react -D
但是就这样的话,我们没办法在class类中,使用state = {},函数名 = ()=> {}等等方法,怎么办呢?解决方案:@babel/plugin-proposal-class-properties
// 修改.babelrc文件增加plugins
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3
}
],
"@babel/preset-react"
],
"plugins": [ // 配置class类中,可以使用state = {},函数名 = ()=> {}, 地址: https://babeljs.io/docs/en/babel-plugin-proposal-class-properties
[
"@babel/plugin-proposal-class-properties",
{
"loose": true
}
]
]
}
测试:
index.html中添加个宿主容器:<div id="root"></div>
index.js(jsx)中添加:
import React, { Component } from "react";
import ReactDom from "react-dom";
import axios from 'axios';
class Home extends Component {
state = {
count: 1,
list: []
}
btnclick = (num) => {
this.setState({
count: this.state.count + num
});
}
componentDidMount(){
axios.get('/apis/getUser').then(res => {
const {data: {list}} = res;
this.setState({
list
});
});
}
render() {
const { list, count } = this.state;
return <div>
<button onClick={() => this.btnclick(1)}>加</button>
<span>{count}</span>
<button onClick={() => this.btnclick(-1)}>减</button>
{
list.map(item => <p key={item.id}>{item.id} - {item.name} - {item.age}</p>)
}
</div>
}
}
ReactDom.render(<Home />, document.getElementById('root'));