Fork me on GitHub

webpack14--webpack中一些工程化的构建

webpack中关于Library的打包

我们先新建一个项目:libiary

1
npm init -y

然后安装一波webpack

1
npm install webpack webpack-cli --save

·`

在src目录下新建几个库文件
math.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export function add(a, b) {
return a + b;
}
export function minus(a, b) {
return a - b;
}
export function multipy(a, b) {
return a * b;
}
export function division(a, b) {
return a / b;
}

String.js

1
2
3
export function join(a,b){
return a+''+b;
}

然后新建一个index.js

1
2
3
4
import * as math from './math';
import * as string from './string';
export default { math,string }

然后在根目录下建立一个webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
const path = require('path');
module.exports = {
mode:'production',
entry:'./src/index.js',
output:{
path:path.resolve(__dirname,'dist'),
filename:'library.js',
library:'library',
// 挂载的地方
libraryTarget:'umd'
}
}

然后把package.json的命令修改一波:

1
2
3
"scripts": {
"build":"webpack"
},

此时运行npm run build命令打包到dist目录下面有一个library.js

然后新建一个index.html文件,在里面引入一波library.js

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src='./library.js'></script>
</head>
<body>
</body>
</html>

然后用chrome浏览器打开,在控制台输出library就可以看到这个类库已经被封装成功了.

打包库的时候我们需要配置的额外的参数有:

1
2
library:'library',
libraryTarget:'umd'

打包第三方类库(Library)

我们把string.js的代码修改一波

1
2
3
4
import _ from 'lodash'
export function join(a,b){
return _.join([a,b],' ')
}

这样用户引入我们的库可以使用:

1
imprt library from 'library';

由于我们在里面已经打包过了lodash
如果用户需要再次引入lodash则会引发一系列问题

为了解决这个问题,我们需要在webpack配置文件里面新增一些配置

1
2
3
4
5
6
7
8
9
10
11
12
const path = require('path');
module.exports = {
mode:'production',
entry:'./src/index.js',
externals:["lodash"],
output:{
path:path.resolve(__dirname,'dist'),
filename:'library.js',
library:'library',
libraryTarget:'umd'
}
}

externals这个配置表示我们在打包过程中忽略掉lodash这个库,这样我们打包的体积会减少很多,但是这样用户使用我们的库的时候,需要自己去引入一波lodash

发布一个npm包

我们把上面这些东西写完之后,想要让别人能够引入我们写的一些npm包,我们把打包好的代码放在dist目录下面的library.js文件中去了.

然后修改一波package.json信息(把main的地址换到要发布的js代码中去)

1
"main":'./dist/library.js'

然后去npm官网注册一个账号

1
2
npm adduser # 添加用户和密码
npm publish # 把库直接发布到npm的仓库上面去

要注意每个库的名字在npm仓库里面都是唯一的,我们需要把名字设置得独特一点,设置package.json里面的name字段.

pwa的打包配置

pwa的实现的技术就是当你第一次访问一个网站的时候成功了,当服务器挂了之后,第二次去访问的时候他会在本地生成一份缓存从而可以使你能够去访问网页.

我们现在自己这边的webpack(之前的那些配置)安装一些东西

1
npm install http-server -D

然后把package.json里面的scripts里面添加一个运行代码的配置项,

1
"start":"http-server dist",

然后安装一波pwd配置

npm install workbox-webpack-plugin -D

然后在webpack.prod.js里面对其进行一波配置:

1
2
3
4
5
6
7
8
9
const WorkBoxPlugin = require("workbox-webpack-plugin");
// ...some codes...
plugins:[
// ...
new WorkBoxPlugin.GenerateSW({
clientsClaim:true,
skipWaiting: true
})
]

然后去运行npm run build,这样打包会多生成一个service-work.js文件.

这时我们去index.js里面去添加一些代码

1
2
3
4
5
6
7
8
9
10
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('service-worker registed');
}).catch(error => {
console.log('service-worker register error');
})
})
}

然后同时使用npm run buildnpm run start命令,这样看控制台的信息输出.

这样即使我们的服务器崩溃掉,我们仍然能够使用缓存去处理.

使用webpackDevServer实现请求的转发

我们利用之前写的一波代码来进行webpackDevServer请求的转发,当然这里要记得把之前使用过PWA的服务器的缓存清空.

这里其实就相当于把整个项目配置到了能够支持react开发的底部,我们页面里面的react代码为index.js

1
2
3
4
5
6
7
8
9
10
import React, { Component } from 'react';
import ReactDom from 'react-dom';
class App extends Component {
render() {
return <div>Hello World</div>
}
}
ReactDom.render(<App />, document.getElementById('root'));

我们来使用一个第三方模块来进行请求的发送

npm install axios –save

在react代码里面添加一个axios发送请求的函数

1
2
3
4
5
componentDidMount(){
axios.get('http://www.dell-lee.com/react/api/header.json').then(res=>{
console.log(res);
})
}

当我们运行npm run start的时候打开浏览器页面,会发现对应的请求信息会输出在控制台上,于是这里就涉及到一些跨域的问题了.

这里我们请求的是一个其他IP地址的接口,而我们本地起的项目则是localhost:8080,但是如果我们在服务器上面配置过跨域请求,这里后端仍然能够成功返回数据的.

一般在利用axios进行请求的时候,我们不会直接输入服务器相对应的地址,而是:

1
2
3
4
5
componentDidMount(){
axios.get('/react/api/header.json').then(res=>{
console.log(res);
})
}

然后在webpack.config.js里面配置一个请求转发:

1
2
3
4
5
6
7
module.exports = {
devServer: {
proxy: {
'/react/api':'http://wwww/dell-lee.com'
}
}
}

这样每次当我们去请求以/react/api开头的数据接口的时候,webpack的devServer都会帮我们转发到后面的那个域名下面去.

这样我们同样也能够请求到数据.

1
2
3
4
5
6
7
8
9
10
11
12
module.exports = {
devServer: {
proxy: {
'/react/api':{
target:'http://www.dell-lee.com',
pathRewrite: {
'header.json':'demo.json'
}
}
}
}
}

上面这个配置的使用场景为后端接口还没有开发完成,给了一个叫做demo.json的预备接口,我们不需要在源代码里面把header.json修改为demo.json,而是直接通过pathRewrite将header.json转为demo.json,这样后续后端将接口开发完成之后,我们只需要将pathRewrite注释掉即可.

如果是https的网址配置,在proxy下面的那些配置下面加个secure: false.

做代理转发要记得加一个changeOrigin:true的配置项

更多的配置(多域名的转发配置)可以参考官网

webpackDevServer解决单页路由问题

继续以react项目作为例子:
首先引入react-router-dom来作为例子:

下面是一个很常规的react项目的入口文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React, { Component } from 'react';
import { BrowserRouter,Route } from 'react-router-dom';
import ReactDom from 'react-dom';
import Home from './home';
import List from './list';
class App extends Component {
render() {
return(
<BrowserRouter>
<div>
<Route exact path='/' component={Home}/>
<Route path='/list' component={List}/>
</div>
</BrowserRouter>
)
}
}
ReactDom.render(<App />, document.getElementById('root'));

然后我们根目录下新建两个组件的代码

home.js

1
2
3
4
5
6
7
8
9
import React from 'react';
class Home extends React.Component{
render(){
return (
<div>Home page</div>
)
}
}
export default Home;

list.js

1
2
3
4
5
6
7
8
9
import React from 'react';
class List extends React.Component{
render(){
return(
<div>list</div>
)
}
}
export default List;

这个时候我们去运行npm run start的时候是能够访问到根路径下的home的,但是去访问list这个路由的时候是访问不到的,为了解决这个问题,我们需要使用webpackDevServer的相关配置去解决

1
2
3
4
5
module.exports = {
devServer:{
historyApiFallback: true,
}
}

保存之后重新启动我们的项目,会发现这个时候之前的问题已经被解决了,我们访问list的时候,已经能够访问到我们想要的文件的样子了.

配置了这个参数之后,无论我们之后访问什么路由,它都会加载index.html里面的内容.

一般来说,在进行前端开发的时候,我们只需要将这个参数设置成true就行了

详细的配置项可以去参考官网中关于这一部分的介绍.

-------------本文结束感谢您的阅读-------------