Vue webpack boilerplate 的一些捣腾

最近在公司内部推 Vuejsvue-cli webpack 生成的项目无法满足现有的需求,于是乎开始改造 vue-cli 初始化的项目, 主要解决项目多页面和外部引入样式文件没有 autoprefixer 的问题。

多页面改造

vue webpack 模板默认是 SPA 项目,改成多页面则需要把单入口变为多入口,生成多个html文件。

项目结构

|—— src
  |—— assets
  |—— components      // 多个页面间的公共组件
  |—— pages 
    |—— hello
      |—— hello.vue   // 页面主vue文件,和文件夹一致方便搜索
      |—— index.html  // html模板文件
      |—— main.js     // 入口文件

pages 文件夹下每个页面都新建一个文件夹,固定三个文件 index.htmlmain.jspage.vue , 后续会有代码来识别产生多入口

构建代码修改

构建逻辑部分需要自定识别 pages 下的文件夹,生成多个 entry

首先,增加一个 page.js 初始化所有的页面信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// page.js
var glob = require('glob');
var path = require('path');
var fs = require('fs');
var chalk = require('chalk');

var ENTRY = 'main.js';
var PAGE_FLODER = path.resolve(__dirname, '../src/pages/');
var PAGES = PAGE_FLODER + '/**/' + ENTRY;
var TEMPLATE = 'index.html';

function initPages() {
var pages = {};
glob.sync(PAGES).forEach(function (entry) {
var pageName = getPageName(entry);
var templatePath = getTemplatePath(entry);
if (!fs.existsSync(templatePath)) {
console.log(chalk.yellow(pageName + '找不到模板文件'));
return;
}

pages[pageName] = {
name: pageName,
entry: entry,
template: templatePath
};
});

return pages;
}

function getPageName(filePath) {
return filePath.substring(PAGE_FLODER.length + 1, filePath.indexOf(ENTRY) - 1);
}

function getTemplatePath(filePath) {
var templatePath = filePath.substring(0, filePath.indexOf(ENTRY));
templatePath += TEMPLATE;
return templatePath;
}

module.exports = initPages();

然后 修改 config/index.js

1
2
3
4
module.exports = {
pages: require('./page'), // 增加page的配置
// ...
};

接下,utils.js 增加两个函数用来生成多个 entryHtmlWebpackPlugin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// utils.js
//...
exports.getEntry = function () {
var entry = {};
Object.keys(config.pages).forEach(function (name) {
entry[name] = config.pages[name].entry;
});
return entry;
}

exports.getHtmlPlugin = function () {
var assetsSubDirectory = process.env.NODE_ENV === 'production' ?
config.build.assetsSubDirectory :
config.dev.assetsSubDirectory;
return Object.keys(config.pages).map(function (name) {
return new HtmlWebpackPlugin ({
template: config.pages[name].template,
filename: name + '.html',
inject: true,
chunks: ['vendor', 'manifest', name],
minify: env === 'production' ? {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
} : undefined,
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: env === 'production' ? 'dependency' : undefined
})
})
}

最后改动 webpack.base.conf.jswebpack.dev.conf.jswebpack.prod.conf.js

1
2
3
4
5
6
// webpack.base.conf.js
// ...
module.exports = {
entry: utils.getEntry() // 多入口配置
// ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// webpack.dev.conf.js
// ...
module.exports = merge(baseWebpackConfig, {
// ...
plugins: [
new webpack.DefinePlugin({
'process.env': config.dev.env
}),
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
].concat(utils.getHtmlPlugin()), // 加入生成的多页面 HtmlWebpackPlugin
});
1
2
3
4
// webpack.prod.conf.js
//...
webpackConfig.plugins = webpackConfig.plugins.concat(utils.getHtmlPlugin()); // 加上这行代码
//...

ok,大功告成, 这样一来就变为多页面项目了(这样一来每个页面至少需要三个文件,自己写了一个atom插件,新建页面时自动生成相关文件和基础代码)。

js内引入css没有 autoprefixer

.vue 文件写的样式都会经过 postcss 处理,但是项目中重构和js需要分开工作,所以需要将css文件独立出去,再在入口文件中引入,这是发现没有样式没有进过 postcss 处理.

这里需要在样式加载时使用 postcss-loader 处理

1
npm install postcss-loader --save-dev
1
2
3
4
5
6
7
8
9
10
11
12
13
// utils.js
exports.cssLoaders = function (options) {
// ...
return {
css: generateLoaders(['css', 'postcss']),
postcss: generateLoaders(['css', 'postcss']),
less: generateLoaders(['css', 'postcss', 'less']),
sass: generateLoaders(['css', 'postcss', 'sass?indentedSyntax']),
scss: generateLoaders(['css', 'postcss', 'sass']),
stylus: generateLoaders(['css', 'postcss', 'stylus']),
styl: generateLoaders(['css', 'postcss', 'stylus'])
};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// webpack.base.conf.js
var postcssConfig = [
require('autoprefixer')({
browsers: ['last 5 versions', 'android >= 4.2', 'ios >= 7']
})
];

module.exports = {
// ...
postcss: postcssConfig, // 增加postcss配置
vue: {
loaders: utils.cssLoaders({
sourceMap: useCssSourceMap
}),
postcss: postcssConfig
}
}

最后

最近又发现 vue webpack 模板又升级到了 webpack 2.2 马上准备入一波坑了。

文章目录
  1. 1. 多页面改造
    1. 1.1. 项目结构
    2. 1.2. 构建代码修改
  2. 2. js内引入css没有 autoprefixer
  3. 3. 最后
,