## vue+typescript+webpack4 项目搭建步骤
> 前言:
因为最近才开始接触Typescript,然后首先就是搭建环境,而网上教程时间比较久而且不全,所以在这里记录下手把手的详细脚印。😂 🎉🎉🎉
源码地址请戳 👇👇👇
[vue-ts-init](https://github.com/persist-xyz/vue-ts-init)
### 1、初始化项目
```
vue init webpack vue-ts-init
cd vue-ts-init
npm install
```
脚手架项目webpack版本为3.6.0
### 2、webpack@3.6.0升级至webpack@4.37.0
方法一:使用yarn安装
```
yarn upgrade webpack@4.6.0
yarn add webpack-dev-server webpack-cli -D
```
方法二:手动修改package.json中webpack版本,重新安装,完成后
运行 `npm run build`, 报错
#### 1、webpack.optimize.CommonsChunkPlugin
`Error: webpack.optimize.CommonsChunkPlugin has been removed, please use config.optimization.splitChunks instead`
原因:`CommonsChunkPlugin`已被webpack4废弃,推荐使用`SplitChunkPlugin`抽离公共模块
解决:找到 /build/webpack.prod.conf.js ,去掉如下配置
```javascript
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
)
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
```
/build/webpack.prod.conf.js,添加
```javascript
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
// 添加如下配置
optimization: {
splitChunks: {
cacheGroups: {
commons: {
chunks: "all",
minChunks: 2,
maxInitialRequests: 5, // The default limit is too small to showcase the effect
minSize: 0 // This is example is too small to create commons chunks
},
vendor: {
test: /node_modules/,
chunks: "all",
name: "vendor",
priority: 10,
enforce: true
}
}
}
},
......
})
```
附:[官方的例子 common-chunk-and-vendor-chunk](https://github.com/webpack/webpack/tree/master/examples/common-chunk-and-vendor-chunk)
```javascript
optimization: {
//提取公共模块,webpack4去除了CommonsChunkPlugin,使用SplitChunksPlugin作为替代
//主要用于多页面
//例子代码 https://github.com/webpack/webpack/tree/master/examples/common-chunk-and-vendor-chunk
//SplitChunksPlugin配置,其中缓存组概念目前不是很清楚
splitChunks: {
// 表示显示块的范围,有三个可选值:initial(初始块)、async(按需加载块)、all(全部块),默认为all;
chunks: "all",
// 表示在压缩前的最小模块大小,默认为0;
minSize: 30000,
//表示被引用次数,默认为1
minChunks: 1,
//最大的按需(异步)加载次数,默认为1;
maxAsyncRequests: 3,
//最大的初始化加载次数,默认为1;
maxInitialRequests: 3,
// 拆分出来块的名字(Chunk Names),默认由块名和hash值自动生成;设置ture则使用默认值
name: true,
//缓存组,目前在项目中设置cacheGroup可以抽取公共模块,不设置则不会抽取
cacheGroups: {
//缓存组信息,名称可以自己定义
commons: {
//拆分出来块的名字,默认是缓存组名称+"~" + [name].js
name: "test",
// 同上
chunks: "all",
// 同上
minChunks: 3,
// 如果cacheGroup中没有设置minSize,则据此判断是否使用上层的minSize,true:则使用0,false:使用上层minSize
enforce: true,
//test: 缓存组的规则,表示符合条件的的放入当前缓存组,值可以是function、boolean、string、RegExp,默认为空;
test:""
},
//设置多个缓存规则
vendor: {
test: /node_modules/,
chunks: "all",
name: "vendor",
//表示缓存的优先级
priority: 10,
enforce: true
}
}
}
}
```
#### 2、compilation.mainTemplate.applyPluginsWaterfall
再运行 `npm run build`, 报错
```
building for production.../Users/xyz_persist/front_end/ts/vue-ts-init2/node_modules/html-webpack-plugin/lib/compiler.js:81
var outputName = compilation.mainTemplate.applyPluginsWaterfall('asset-path', outputOptions.filename, {
^
TypeError: compilation.mainTemplate.applyPluginsWaterfall is not a function
```
原因:`html-webpack-plugin`未升级版本导致
解决:升级 `html-webpack-plugin` 版本
```
npm i html-webpack-plugin@3.2.0
npm i vue-loader@15.7.1
```
#### 3、Error: Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead
再运行 `npm run build`, 报错
```
⠋ building for production...(node:13954) DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead
⠼ building for production...(node:13954) UnhandledPromiseRejectionWarning: Error: Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead
```
原因:extract-text-webpack-plugin还不能支持webpack4.0.0以上的版本
[官网extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin)
解决:升级 `extract-text-webpack-plugin` 版本
`npm i extract-text-webpack-plugin@next -D`
> 注:extract-text-webpack-plugin作用:
>
> 将所有入口chunk中引用的.css抽离到独立的css文件中,而不再内嵌到JS bundle中。
>
> 如果样式文件大小较大,会更快提前加载,因为`CSS bundle` 会跟 `JS bundle`并行加载
#### 4、TypeError: Cannot read property 'eslint' of undefined
再运行 `npm run build`, 报错
```
TypeError: Cannot read property 'eslint' of undefined
at Object.module.exports (/Users/xyz_persist/front_end/ts/vue-ts-init2/node_modules/eslint-loader/index.js:148:18)
TypeError: Cannot read property 'vue' of undefined
at Object.module.exports (/Users/xyz_persist/front_end/ts/vue-ts-init2/node_modules/vue-loader/lib/loader.js:61:18)
@ ./src/main.js 4:0-24 13:21-24
......
```
原因:eslint-loader、vue-loader版本问题
解决:
```
npm i eslint-loader@2.2.1 -D
npm i vue-loader@15.7.1 -D
```
#### 5、Make sure to include VueLoaderPlugin in your webpack config
再运行 `npm run build`, 报错
```reStructuredText
ERROR in ./src/App.vue
Module Error (from ./node_modules/vue-loader/lib/index.js):
vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.
@ ./src/main.js 4:0-24 13:21-24
```
原因:Vue-loader在15.*之后的版本都是 vue-loader的使用都是需要伴生 VueLoaderPlugin