VUE-CLI 创建的工程postcss autoprefixer build模式与dev 不相同

各位大神好

目前在vue项目中需要兼容到ios8版本, 所以在.postcssrc.js中添加了兼容选项, 但在实际打包时发现和dev模式下的css不一样, 如上贴出代码

.postcssrc.js

// https://github.com/michael-ciniawsky/postcss-load-config

module.exports = {
    "plugins": {
        // to edit target browsers: use "browserlist" field in package.json
        // https://github.com/ai/browserslist#config-file
        "autoprefixer": {
            browsers: ['defaults', 'ios >= 6.0']
        }
    }
};

dev 模式下postcss 生成的代码

clipboard.png

build模式下postcss 生成的代码

clipboard.png

webpack.base.conf.js

let path = require('path');
let utils = require('./utils');
let config = require('../config');
let vueLoaderConfig = require('./vue-loader.conf');
let fs = require('fs');

function resolve(dir) {
    return path.join(__dirname, '..', dir)
}

let alias = {
    'vue$': 'vue/dist/vue.esm.js',
    '@': resolve('src')
};

// 获取所有文件夹  设置别名
let dirList = fs.readdirSync(path.join(__dirname, '../src'));

dirList.forEach(function (item) {
    // 判断是否为文件夹
    let isDir = fs.lstatSync(path.join(__dirname, '../src/' + item)).isDirectory();
    if (isDir) {
        alias[`_${item}`] = path.join(__dirname, '../src/' + item);
    }
});

module.exports = {
    entry: {
        app: ["./src/main.js"]
    },
    output: {
        path: config.build.assetsRoot,
        filename: '[name].js',
        publicPath: process.env.NODE_ENV === 'production'
            ? config.build.assetsPublicPath
            : config.dev.assetsPublicPath
    },
    resolve: {
        extensions: ['.js', '.vue', '.json'],
        alias: alias
    },
    module: {
        rules: [
            {
                test: /\.(js|vue)$/,
                loader: 'eslint-loader',
                enforce: 'pre',
                include: [resolve('src'), resolve('test')],
                options: {
                    formatter: require('eslint-friendly-formatter')
                }
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: vueLoaderConfig
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                include: [resolve('src'), resolve('test')]
            },
            {
                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
                loader: 'url-loader',
                options: {
                    limit: 10000,
                    name: utils.assetsPath('img/[name].[hash:7].[ext]')
                }
            },
            {
                test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
                loader: 'url-loader',
                options: {
                    limit: 10000,
                    name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
                }
            }
        ]
    }
};

webpack.dev.conf.js

let utils = require('./utils');
let webpack = require('webpack');
let config = require('../config');
let merge = require('webpack-merge');
let baseWebpackConfig = require('./webpack.base.conf');
let HtmlWebpackPlugin = require('html-webpack-plugin');
let FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');

// add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
    baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
});

module.exports = merge(baseWebpackConfig, {
    module: {
        rules: utils.styleLoaders({sourceMap: config.dev.cssSourceMap})
    },
    externals: {
        vue: 'window.Vue',
        'vue-router': 'window.VueRouter',
        'vuex': 'window.Vuex',
        'vue-lazyload': 'window.VueLazyload',
        "async-validator": "window.asyncValidator",
        "axios": "window.axios",
        "moment": "window.moment",
        // "vue-swipe": "window.vueSwipe",
    },
    // cheap-module-eval-source-map is faster for development
    devtool: '#cheap-module-eval-source-map',
    plugins: [
        new webpack.DefinePlugin({
            'process.env': config.dev.env
        }),
        // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoEmitOnErrorsPlugin(),
        // https://github.com/ampedandwired/html-webpack-plugin
        new HtmlWebpackPlugin({
            filename: 'view.html',
            template: 'view.html',
            inject: true
        }),
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.html',
            inject: false
        }),
        new FriendlyErrorsPlugin()
    ]
});

webpack.prod.conf.js

const path = require('path');
const utils = require('./utils');
const webpack = require('webpack');
const config = require('../config');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
/*var env = process.env.NODE_ENV === 'testing'
 ? require('../config/test.env')
 : config.build.env*/

let buildDirName = process.env.buildEnv === 'online' ? 'online/' + config.build.buildDirName : 'dev/' + config.build.buildDirName;

const env = process.env.NODE_ENV === 'testing'
    ? require('../config/test.env')
    : {
        NODE_ENV: `"${process.env.NODE_ENV}"`
    };
let webpackConfig = merge(baseWebpackConfig, {
    module: {
        rules: utils.styleLoaders({
            sourceMap: config.build.productionSourceMap,
            extract: true
        })
    },
    devtool: config.build.productionSourceMap ? '#source-map' : false,
    output: {
        path: path.resolve(__dirname, '../dist/' + buildDirName),
        filename: utils.assetsPath('js/[name].[chunkhash].js'),
        chunkFilename: utils.assetsPath('js/[id].[chunkhash].js'),
        publicPath: ''
    },
    externals: {
        vue: 'window.Vue',
        'vue-router': 'window.VueRouter',
        'vuex': 'window.Vuex',
        'vue-lazyload': 'window.VueLazyload',
        "async-validator": "window.asyncValidator",
        "axios": "window.axios",
        "moment": "window.moment",
        // "vue-swipe": "window.vueSwipe",
    },
    plugins: [
        // http://vuejs.github.io/vue-loader/en/workflow/production.html
        new webpack.DefinePlugin({
            'process.env': env
        }),
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            },
            sourceMap: true
        }),
        // extract css into its own file
        new ExtractTextPlugin({
            filename: utils.assetsPath('css/[name].[contenthash].css')
        }),
        // Compress extracted CSS. We are using this plugin so that possible
        // duplicated CSS from different components can be deduped.
        new OptimizeCSSPlugin({
            cssProcessorOptions: {
                safe: true
            }
        }),
        // generate dist index.html with correct asset hash for caching.
        // you can customize output by editing /index.html
        // see https://github.com/ampedandwired/html-webpack-plugin
        /*new HtmlWebpackPlugin({
            // 备用入口
            filename: '../view.html',
            template: 'view.html',
            inject: true,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
                // more options:
                // https://github.com/kangax/html-minifier#options-quick-reference
            },
            // necessary to consistently work with multiple chunks via CommonsChunkPlugin
            chunksSortMode: 'dependency'
        }),*/
        new HtmlWebpackPlugin({
            filename: '../../index.html',
            template: 'index.html',
            inject: false,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
                // more options:
                // https://github.com/kangax/html-minifier#options-quick-reference
            },
            // necessary to consistently work with multiple chunks via CommonsChunkPlugin
            chunksSortMode: 'dependency'
        }),
        new HtmlWebpackPlugin({
            filename: 'view.html',
            template: 'view.html',
            inject: true,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
                // more options:
                // https://github.com/kangax/html-minifier#options-quick-reference
            },
            // necessary to consistently work with multiple chunks via CommonsChunkPlugin
            chunksSortMode: 'dependency'
        }),
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.html',
            inject: false,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
                // more options:
                // https://github.com/kangax/html-minifier#options-quick-reference
            },
            // necessary to consistently work with multiple chunks via CommonsChunkPlugin
            chunksSortMode: 'dependency'
        }),
        // split vendor js into its own file
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            minChunks: function (module, count) {
                // 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')
                    ) === 0
                )
            }
        }),
        // 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',
            chunks: ['vendor']
        }),
        // copy custom static assets
        new CopyWebpackPlugin([
            {
                from: path.resolve(__dirname, '../static'),
                to: config.build.assetsSubDirectory,
                ignore: ['.*']
            }
        ])
    ]
});

if (config.build.productionGzip) {
    let CompressionWebpackPlugin = require('compression-webpack-plugin')
    
    webpackConfig.plugins.push(
        new CompressionWebpackPlugin({
            asset: '[path].gz[query]',
            algorithm: 'gzip',
            test: new RegExp(
                '\\.(' +
                config.build.productionGzipExtensions.join('|') +
                ')$'
            ),
            threshold: 10240,
            minRatio: 0.8
        })
    )
}

if (config.build.bundleAnalyzerReport) {
    let BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
    webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

package.json

{
    ...,
    devDependencies: {
        ...,
        "webpack": "^2.6.1",
        "postcss-cssnext": "^3.0.2",
        "postcss-import": "^11.0.0",
        "postcss-load-config": "^1.2.0",
        "postcss-loader": "^2.0.8",
        "postcss-plugin": "^1.0.0"
    }
}
阅读 8.7k
3 个回答

问题已经找到了 是 optimize-css-assets-webpack-pluginautoprefixer 之间互相冲突

解决办法

webpack.prod.conf.js中去除optimize-css-assets-webpack-plugin插件

const path = require('path');
const utils = require('./utils');
const webpack = require('webpack');
const config = require('../config');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
/*var env = process.env.NODE_ENV === 'testing'
 ? require('../config/test.env')
 : config.build.env*/

let buildDirName = process.env.buildEnv === 'online' ? 'online/' + config.build.buildDirName : 'dev/' + config.build.buildDirName;

const env = process.env.NODE_ENV === 'testing'
    ? require('../config/test.env')
    : {
        NODE_ENV: `"${process.env.NODE_ENV}"`
    };
let webpackConfig = merge(baseWebpackConfig, {
    module: {
        rules: utils.styleLoaders({
            sourceMap: config.build.productionSourceMap,
            extract: true
        })
    },
    devtool: config.build.productionSourceMap ? '#source-map' : false,
    output: {
        path: path.resolve(__dirname, '../dist/' + buildDirName),
        filename: utils.assetsPath('js/[name].[chunkhash].js'),
        chunkFilename: utils.assetsPath('js/[id].[chunkhash].js'),
        publicPath: ''
    },
    externals: {
        vue: 'window.Vue',
        'vue-router': 'window.VueRouter',
        'vuex': 'window.Vuex',
        'vue-lazyload': 'window.VueLazyload',
        "async-validator": "window.asyncValidator",
        "axios": "window.axios",
        "moment": "window.moment",
        // "vue-swipe": "window.vueSwipe",
    },
    plugins: [
        // http://vuejs.github.io/vue-loader/en/workflow/production.html
        new webpack.DefinePlugin({
            'process.env': env
        }),
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            },
            sourceMap: true
        }),
        // extract css into its own file
        new ExtractTextPlugin({
            filename: utils.assetsPath('css/[name].[contenthash].css')
        }),
        // Compress extracted CSS. We are using this plugin so that possible
        // duplicated CSS from different components can be deduped.
        
        
        // 这里去除
        
        /* new OptimizeCSSPlugin({
            cssProcessorOptions: {
                safe: true
            }
        }), */
        
        
        
        
        // generate dist index.html with correct asset hash for caching.
        // you can customize output by editing /index.html
        // see https://github.com/ampedandwired/html-webpack-plugin
        /*new HtmlWebpackPlugin({
            // 备用入口
            filename: '../view.html',
            template: 'view.html',
            inject: true,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
                // more options:
                // https://github.com/kangax/html-minifier#options-quick-reference
            },
            // necessary to consistently work with multiple chunks via CommonsChunkPlugin
            chunksSortMode: 'dependency'
        }),*/
        new HtmlWebpackPlugin({
            filename: '../../index.html',
            template: 'index.html',
            inject: false,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
                // more options:
                // https://github.com/kangax/html-minifier#options-quick-reference
            },
            // necessary to consistently work with multiple chunks via CommonsChunkPlugin
            chunksSortMode: 'dependency'
        }),
        new HtmlWebpackPlugin({
            filename: 'view.html',
            template: 'view.html',
            inject: true,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
                // more options:
                // https://github.com/kangax/html-minifier#options-quick-reference
            },
            // necessary to consistently work with multiple chunks via CommonsChunkPlugin
            chunksSortMode: 'dependency'
        }),
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.html',
            inject: false,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
                // more options:
                // https://github.com/kangax/html-minifier#options-quick-reference
            },
            // necessary to consistently work with multiple chunks via CommonsChunkPlugin
            chunksSortMode: 'dependency'
        }),
        // split vendor js into its own file
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            minChunks: function (module, count) {
                // 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')
                    ) === 0
                )
            }
        }),
        // 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',
            chunks: ['vendor']
        }),
        // copy custom static assets
        new CopyWebpackPlugin([
            {
                from: path.resolve(__dirname, '../static'),
                to: config.build.assetsSubDirectory,
                ignore: ['.*']
            }
        ])
    ]
});

if (config.build.productionGzip) {
    let CompressionWebpackPlugin = require('compression-webpack-plugin')
    
    webpackConfig.plugins.push(
        new CompressionWebpackPlugin({
            asset: '[path].gz[query]',
            algorithm: 'gzip',
            test: new RegExp(
                '\\.(' +
                config.build.productionGzipExtensions.join('|') +
                ')$'
            ),
            threshold: 10240,
            minRatio: 0.8
        })
    )
}

if (config.build.bundleAnalyzerReport) {
    let BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
    webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

应该还有更优的解决方案, 后续研究, 打包后发现代码还是压缩了的

我使用的解决方案是把 package.json 中修改 last 2 versions 为 7

   "browserslist": [
     "> 1%",
-    "last 2 versions",
+    "last 7 versions",
     "not ie <= 8"
   ]
新手上路,请多包涵

optimize-css-assets-webpack-plugin 内部用的是cssnano做的优化,把配置改下就可以了,https://cssnano.co/guides/opt...

new OptimizeCSSPlugin({
   cssProcessorOptions: {
      autoprefixer: false
   }
})
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题