本文的
webpack
配置是基于vue-cli
改良的,且面向有一定基础的人
初始准备工作
- 使用
vue init webpack
指令构建好一个初始的项目,删除无关的东西,更改一下项目目录如下
并且把src
static
中的文件清空 -
删除
package.json
中无关的依赖- "vue": "^2.4.2" - "vue-loader": "^13.0.4", - "vue-style-loader": "^3.0.1", - "vue-template-compiler": "^2.4.2",
- 删除
build/vue-loader.conf.js
-
在
src
中创建2个文件夹分别为index
about
,在其中再创建3个文件index.html
index.css
index.js
目录结构为build config src |———— views | |———— index | | |————— index.html | | |————— index.css | | |————— index.js | | | |———— index2 | |————— index.html | |————— index.css | |————— index.js |———— static // 存放静态资源 |———— lib // 存放第三方库 把每个页面当做一个模块,这样的模块化方便项目管理,一眼瞄过去也比较清晰
开始
-
更改
webpack.base.conf.js
把与vue
相关的配置删除module.exports = { resolve: { - extensions: ['.js', '.vue', '.json'], + extensions: ['.js', '.json'], alias: { - 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), } }, module: { rules: [ - { - test: /\.vue$/, - loader: 'vue-loader', - options: vueLoaderConfig - }, { test: /\.js$/, loader: 'babel-loader', - include: [resolve('src'), resolve('test')] + include: [resolve('src')] }, ........
-
在
build/utils.js
中,更改配置。不得不说utils.js
中生成各种loader
确实写的很棒,已经把所有的与css
相关的loader
涵盖进去,若要使用,只需要安装相关的loader
即可if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, - fallback: 'vue-style-loader' + fallback: 'style-loader' }) } else { - return ['vue-style-loader'].concat(loaders) + return ['style-loader'].concat(loaders) }
我们不再需要
vue-style-loader
只需要普通的style-loader
即可 -
既然是多页面,那么就肯定是有多个入口
entry: { index: './src/index/index.js', about: './src/about/index.js' },
这里科普一下,这里的
entry
路径是相对于webpack
编译时的基础目录context
(也就是package.json
所在目录)。路径的详细解释可以参考这篇文章
页面少的时候还ok,但是如果页面多起来的时候全部都要自己手动去配置确实是挺麻烦的。所以这里我们来写一段函数进行批量处理-
首先我们在
build
文件夹下新建文件pages.json
用于存放页面的信息{ "root": "./src", // 页面存放的目录地址 "pages": [ // 页面名, 打包生成的html,css,js文件也是这个名字 "index", "about" ] }
-
再在同个目录下创建
pages.conf.js
用来生成页面的路径var config = require('./pages.json') var root = config.root var pages = config.pages function genPagesDir() { var dirs = {} for (var i = 0; i < pages.length; i++) { var a = pages[i] dirs[a] = `${root}/${a}` } return dirs } module.exports = genPagesDir()
-
跟着我们回到
webpack.base.conf.js
增加生成入口配置的函数var pages = require('./pages.conf') ........ function genEntries() { var entries = {} for (var key in pages) { entries[key] = `${pages[key]}/index.js` } return entries }
-
并且把
entry
配置进行更改, 这样就大功告成entry: genEntries()
-
-
入口的配置完成之后,就要进行模板的配置,这里如果不了解
html-webpack-plugin
的,可以先去了解一下,单页应用只有一个页面所以模板就只有一个,那么如果是多页面应用,则可能会存在多个模板,多个模板就必须配置多个HtmlWebpackPlugin
。说简单点就是,有n
个页面,就要在plugins
中写n
个new HtmlWebpackPlugin({ filename: 'index.html', template: 'index.html', inject: true }),
所以这里就必须要再写一个批量生成的函数,和生成入口配置是一个道理的。
var pages = require('./pages.conf') ....... function genHtmlWebpackPlugin() { var arr = []; for (var key in pages) { arr.push(new HtmlWebpackPlugin({ filename: `${key}.html`, template: `${pages[key]}/index.html`, inject: true, chunks: [`${key}`] // chunk为该页面要包含的js文件 })) } return arr; } module.exports = merge(baseWebpackConfig, { .... plugins: [ .... - new HtmlWebpackPlugin({ - filename: 'index.html', - template: 'index.html', - inject: true - }), .... + ].concat(genHtmlWebpackPlugin()) })
filename
是相对于output.publicPath
, 在dev-server
中则是相对于其assetsPublicPath
, 保持这二者相同就是为了更方便的配置template
则是相对于context
(也就是上文提到的)chunks
必须写,不然页面将会把所有打包后的js文件引入 -
webpack.prod.conf.js
的配置也是类似的,这里不再赘述,需要注意的是chunks
需要包含vendor
,manifest
。 还有filename
要用打包目录dist
filename: `${config.build.assetsRoot}/${key}.html`
至此,所有的配置都完成了~
但是,在使用的时候发现,每次要增加一个新目录的时候都要先创建一个目录,然后再创建3个文件,再到pages.json
中添加新增的页面。仔细想想好像还是挺麻烦的。那我们自个写个指令来自动实现这些功能吧!
懒人指令
- 在
build
中创建文件create.js
- 在
package.json
中添加指令"create": "node build/create.js"
开始码代码~
-
我们的预想是通过
npm run create filename
指令完成上述一系列步骤,那么我们就要知道如何去在create.js
中去读取这个filename
。 其实这个参数就在变量process
中,process
是node
的一个全局变量,这里不展开来讲,有兴趣的可以自己去了解。 我们可以试着打印一下process.argv
的内容。
在create.js
中增加以下代码,然后执行npm run create about
, 查看输出var dirname = process.argv; console.log(dirname)
可以看到process.argv
中分别包含了指令的3个部分node
,create.js
,about
所以,process.argv[2]
就是我们想要的dirname
-
创建文件那就需要用到
node
的fs
, 通过fs.mkdir
来创建目录,再通过fs.writeFile
来创建文件。当然我们还需要写一些异常处理的代码, 当指令没有输入filename
或文件夹已存在时,进行提示,chalk
可以让我们的cmd输出看起来更加美观一些。 下面为代码var fs = require('fs') var chalk = require('chalk') var root = require('./pages.json').root var dirname = process.argv[2] var path = `${root}/${dirname}` var htmlTemplate = `<!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>title</title> </head> <body> </body> </html>` if (!dirname) { console.error(chalk.bgRed('Please input the dirname !!!\n')) return } if (fs.existsSync(path)) { console.error(chalk.bgRed('File is already exists !!!\n')) return } function throwErr (err) { if (err) { throw err } } fs.mkdir(path , (err) => { if (!err) { fs.writeFile(`${path}/index.html`, htmlTemplate, throwErr); fs.writeFile(`${path}/index.js`, '', throwErr); fs.writeFile(`${path}/index.css`, '', throwErr); console.log(chalk.bgGreen(' Create success.\n')); } })
到这已经完成了文件的创建功能。
-
-
接下来要写更新
pages.json
的代码,通过fs.readFile
把pages.json
的内容读取进来,读取进来的是json字符串,那么使用JSON.parse
即可将其转为对象,然后再往pages
中增加新的内容,再然后使用JSON.stringify
将其转回字符串写回到文件中。大功告成function updatePages() { var path = 'build/pages.json' var rc = JSON.parse(fs.readFileSync(path, {encoding: 'utf-8'})) rc.pages = rc.pages.concat(dirname) var wc = JSON.stringify(rc) fs.writeFileSync(path, wc) } // 记得在创建完3个文件之后updatePages()进行调用
结束
至此所有的代码已写完了。之后就可以使用懒人指令进行创建文件了。只不过删除的时候不能自动更新,需要自己到pages.json
中进行删除。
熟肉在这
之后还会再写多一片文章,通过使用这个webpack配置来对旧项目进行重构。
新人第一篇文章,有不对的地方望指出。_(:з」∠)_
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。