new parallelUglifyPlugin({
cacheDir: '.cache/',
uglifyJS: {
output: {
comments: false, //false :关闭注释
},
compress: {
warnings: false,
drop_console: true,
collapse_vars: true,
reduce_vars: true,
},
},
sourceMap:true,// 开启sourcemap
})
注意:有的时候, 这个插件第一次运行的时候会报错,报不是空目录,可能是与删除dist目录的插件clean-webpack-plugin 有关,我现在也搞不清楚了,之前在配置的时候,总是报错,把 webpack-parallel-uglify-plugin 注释掉后就可以用了,今天我再运行webpack-parallel-uglify-plugin 时还是报错 ,我先关闭了clean-webpack-plugin ,在运行就可以了。接着又打开clean-webpack-plugin ,不报错了。搞不懂!!!
现在搞清楚了,第一次运行webpack-parallel-uglify-plugin 时不能让.cache(压缩缓存)有内容,必须是空的,或是没有这个目录
// 抽离第三方的代码,也就是生产依赖里的代码,现在是单文件的入口:
entry: {
main: PATHS.app,
//vender:["react","react-dom","antd"],//引用的第三方库
},
mode:"production",
output: {
path: PATHS.build,
filename: filename,
publicPath:PATHS.publicPath,
},
optimization: {
runtimeChunk: {//包清单
name: "manifest"
},
splitChunks: { //拆分公共包
cacheGroups: {
vendor: {//第三方组件
test: /node_modules/,
chunks: "initial",
name: "vendor",
priority: 10,
enforce: true
}
}
}
},
有时需要多文件的入口,这对个文件里就肯定有相同额部分。比如 common.js 是个工具插件,a.js引用了common.js, b.js也引用了common.js。 当我们把a.js和b.js分别作为入口文件的时候,他们两个都加载了common.js,所以可以提供一个公共的js让这两个文件引用,这样减少代码的重复。
// 抽离第三方的代码,也就是生产依赖里的代码,现在是单文件的入口:
entry: {
main: PATHS.main,
home: PATHS.home,
//vender:["react","react-dom","antd"], //引用的第三方库
},
mode:"production",
output: {
path: PATHS.build,
filename: filename,
publicPath:PATHS.publicPath,
},
optimization: {
runtimeChunk: {//包清单
name: "manifest"
},
splitChunks: { //拆分公共包
cacheGroups: {
common: {//项目公共组件,多个入口文件可以用到
chunks: "initial",//指定提取范围[],可以是所有"all"
name: "common",//提取公共代码的js文件名
minChunks: 2,//指定重复代码几次之后就提取出来
maxInitialRequests: 5,
minSize: 0
},
vendor: {//第三方组件
test: /node_modules/,
chunks: "initial",
name: "vendor",
priority: 10,
enforce: true
}
}
}
},
静态资源拷贝插件 copy-webpack-plugin
new copyWebpackPlugin([{
from:__dirname+'/src/assert',//打包的静态资源目录地址
to:'./assert' //打包到dist下面的public
}]),//拷贝静态资源到指定的位置,也就是不用编译这个目录下的文件
按需加载 在webpack 的文件输出配置output中加上按需加载生成js 文件的配置 chunkname ,关于filename 与 chunkname 的理解可以看 https://www.jianshu.com/p/d9ebab57bca1。按需加载是需要搭配js文件里的代码使用的,光设置webpack是什么效果都没有的。拿react的路由做例子,在每一个路由点击的时候加载对应的组件。
output: {
path: PATHS.build,
filename: "js/[name].min.js", // name 对应entry里的入口配置名
publicPath:"./",
chunkFilename: 'js/[name].[chunkhash:5].chunk.js', // 生成对应额chunkhash加在文件名中 ,
//name 对应 用 bundle-loader加载时设置额名字,看下面额例子
// import Apiopt from "bundle-laoder?lazy&name=apiopt!../containner/apiopt/apiopt.js"
},
react 配置 : 在react-router4后不再通过 getComponent来按需加载路由组件,通过bundle-loader更加简化了按需加载。安装 bundle-loader --save-dev 参考文件https://www.vanadis.cn/2017/08/05/react-router-webpack-load-on-demand/
import React ,{Component} from "react";
import { BrowserRouter ,HashRouter , Route ,Switch } from "react-router-dom";
import {Home} from "../component/home.js";
import ApiOpt from "bundle-loader?lazy&name=ApiOpt!../containner/apiopt/apiopt.js";
import Application from "bundle-loader?lazy&name=Application!../containner/application/application.js";
class Bundle extends Componet {
state={
mod:null,
}
componentWillMound(){
this.load(this.props);
}
componentWiillReciveProps(next,props){
if (nextProps.load !== this.props.load) {
this.load(nextProps)
}
}
load(){
this.setState({
mod: null
});
// 这里的 props.load 是用 babel-loader 引入的异步加载函数,不是组件,是下面这样函数,参数是个回调函数
//仔细看这个回调函数,发现它的参数才是真正的组件。使用 require()引入。
// 所以这里又涉及到,我们在导出 模块时候是 怎么的方式。
function(cb) {
Promise.all(
/*! require.ensure | Application */
[__webpack_require__.e("vendors~ApiOpt~Application"),
__webpack_require__.e("vendors~Application"),
__webpack_require__.e("Application")]).then((function(require) {
cb(__webpack_require__(
/*! !../../../node_modules/_babel-loader@7.1.4@babel-loader/lib!./application.js */
"./node_modules/_babel-loader@7.1.4@babel-loader/lib/index.js!./src/containner/application/application.js"));
}).bind(null, __webpack_require__)).catch(__webpack_require__.oe);
}
props.load((mod) => {
this.setState({
// handle both es imports and cjs
mod: mod.default ? mod.default : mod
// 刚开始我不理解这个mod 是啥,现在很清楚了,是个用require 引入的模块
// .default 是我们用的 export default 导出的。 所以 我们用require 时。 module 对象里的 key 值 default
// 要是 我们用 export { } ,这里肯定就不能用default ,因为 module里的key 值就是我们当时定义的模块名
// 然而我们最好使用 export default 导出 ,不然 不然在这个方法里不知道定义的模块名是什么。
})
})
}
render(){
return this.props.children(this.state.mod); // 返回的是真正的组件
}
}
const Loading=()=>{
return (<div>Loading......</div>);
}
const createComponent = (component)=>{
return (
<Bundle load={component}>
(Component) => Component ? <Component {...props} /> : <Loading/>
</Bundle>
);
}
const Routes=(
<Route path="./application" component={createComponent(Appliction)} ></Route>
<Route path="./apiopt" component={createComponent(ApiOpt)} ></Route>
)