UNPKG

3.95 kBJavaScriptView Raw
1'use strict'
2
3const path = require('path')
4const autoprefixer = require('autoprefixer')
5const ExtractTextPlugin = require('extract-text-webpack-plugin')
6const config = require('../../config')
7const maraConf = require(config.paths.marauder)
8const shouldUseRelativeAssetPaths = maraConf.publicPath === './'
9
10const postcssPlugin = [
11 require('postcss-flexbugs-fixes'),
12 autoprefixer(config.postcss)
13]
14
15// css 语法增强
16const postcssPluginAdvanced = [
17 // 提供代码段引入,为了保证引入的代码段能够享受后续的配置
18 // 应确保此插件在插件列表中处于第一位
19 // https://github.com/postcss/postcss-import
20 require('postcss-import')(),
21 // 辅助 postcss-import 插件, 解决嵌套层级的图片资源路径问题
22 require('postcss-url')(),
23 require('postcss-preset-env')(config.postcss),
24 ...postcssPlugin
25]
26
27// Extract CSS when that option is specified
28// (which is the case during production build)
29function wrapLoader(options, loaders) {
30 if (!options.extract) {
31 return [
32 {
33 loader: 'vue-style-loader',
34 options: {
35 // 启用 sourceMap
36 sourceMap: options.sourceMap
37 }
38 }
39 ].concat(loaders)
40 }
41
42 const assets = options.library ? '' : `${config.assetsDir}/css`
43 // 统一使用 POSIX 风格拼接路径,方便基于 / 做逻辑判断
44 const cssFilename = maraConf.hash
45 ? path.posix.join(assets, '[name].[contenthash:8].css')
46 : path.posix.join(assets, '[name].min.css')
47
48 // ExtractTextPlugin expects the build output to be flat.
49 // (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
50 // However, our output is structured with css, js and media folders.
51 // To have this structure working with relative paths, we have to use custom options.
52 const extractTextPluginOptions = shouldUseRelativeAssetPaths
53 ? // Making sure that the publicPath goes back to to build folder.
54 { publicPath: Array(cssFilename.split('/').length).join('../') }
55 : {}
56
57 return ExtractTextPlugin.extract(
58 Object.assign(
59 {
60 use: loaders,
61 fallback: 'vue-style-loader'
62 },
63 extractTextPluginOptions
64 )
65 )
66}
67
68/**
69 * 生成 css loader 配置集合
70 * @param {Object} options 配置参数
71 * @return {Object} 结果对象
72 */
73function cssLoaders(options = {}) {
74 // generate loader string to be used with extract text plugin
75 function generateLoaders(loader, loaderOptions) {
76 let loaders = [
77 {
78 loader: 'css-loader',
79 options: {
80 importLoaders: loader ? 2 : 1,
81 // 启用 sourceMap
82 sourceMap: options.sourceMap
83 }
84 }
85 ]
86 const postcssLoader = {
87 loader: 'postcss-loader',
88 options: {
89 plugins: loader ? postcssPlugin : postcssPluginAdvanced,
90 sourceMap: options.sourceMap
91 }
92 }
93
94 // css 默认使用 postcss-loader 处理
95 // 由于 vue-loader 自带 postcss,略过
96 if (!options.vue) {
97 loaders.push(postcssLoader)
98 }
99
100 // loader 数组反向加载
101 // 确保预处理 loader 在 postcss 之后
102 // 以保证实际优先处理
103 if (loader) {
104 loaders.push({
105 loader: loader + '-loader',
106 options: Object.assign({}, loaderOptions, {
107 sourceMap: options.sourceMap
108 })
109 })
110 }
111
112 return wrapLoader(options, loaders)
113 }
114
115 // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html
116 return {
117 css: generateLoaders(),
118 less: generateLoaders('less'),
119 sass: generateLoaders('sass', { indentedSyntax: true }),
120 scss: generateLoaders('sass')
121 }
122}
123
124// Generate loaders for standalone style files (outside of .vue)
125function styleLoaders(options) {
126 const loaders = cssLoaders(options)
127
128 return Object.keys(loaders).map(ext => ({
129 test: new RegExp('\\.' + ext + '$'),
130 use: loaders[ext]
131 }))
132}
133
134module.exports = {
135 cssLoaders,
136 styleLoaders,
137 postcssPlugin
138}