最近搞vue,用的vue-cli,快速构建开发环境,当然核心还是集成的webpack。之前自己做react的webpack环境配置总觉得差强人意,于是就把vue-cli的迁移过来,感觉还是不错的。对应一般开发需要,下面需要修改的就在build和config目录下的几个文件中
从webpack.base.conf.js 文件开始,无论生产环境还是开发环境都以这个为基础的,
module.exports = { entry: { app: ['./src/js/index.js'],//入口文件 babel: ['babel-polyfill'] //babel-polyfill 和redux 单独打包减小app.js 的打包体积 用于配合externals redux: ['redux','react-redux'],},output: { path: config.build.assetsRoot,filename: '[name].js',publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath,libraryTarget: 'umd' //用于外部引入的 react.js 等 },resolve: { extensions: ['.js','.json'],symlinks: false },module: { rules: [ { test: /\.js$/,loader: 'babel-loader',include: [resolve('src'),resolve('test')],exclude:[resolve('node_modules')],//在node_modules的文件不被babel理会 query: { presets: ['react','stage-2'] } },{ test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,loader: 'url-loader',options: { limit: 10000,name: utils.assetsPath('img/[name].[hash:7].[ext]'),} },{ test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,name: utils.assetsPath('media/[name].[hash:7].[ext]') } },{ test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,name: utils.assetsPath('fonts/[name].[hash:7].[ext]') } },// { // test: /\.less$/,// use: ExtractTextPlugin.extract({ use: extractCssLoaders,fallback: 'style-loader' }),// } ] },// 配置全局使用 plugins: [ new webpack.ProvidePlugin({ "React": "react","ReactDOM": "react-dom","_": "lodash","classnames":"classnames" }),//extract css into its own file new ExtractTextPlugin({ filename: utils.assetsPath('css/[name].[contenthash].css') }),],// 单独提取出 react 减小打包文件大小 externals: { 'react-router': { amd: 'react-router',root: 'ReactRouter',commonjs: 'react-router',commonjs2: 'react-router' },react: { amd: 'react',root: 'React',commonjs: 'react',commonjs2: 'react' },'react-dom': { amd: 'react-dom',root: 'ReactDOM',commonjs: 'react-dom',commonjs2: 'react-dom' } } }
然后再 util.js 文件里,主要就在cssLoaders
exports.cssLoaders = function (options) { options = options || {} var cssLoader = { loader: 'css-loader',options: { minimize: process.env.NODE_ENV === 'production',sourceMap: options.sourceMap,modules: true,localIdentName: '[local]--[hash:base64:6]',//class 名字 代替 } } // generate loader string to be used with extract text plugin function generateLoaders(loader,loaderOptions) { var loaders = [cssLoader]; if (loader) { loaders.push({ loader: loader + '-loader',options: Object.assign({},loaderOptions,{ sourceMap: options.sourceMap }) }) } // Extract CSS when that option is specified //(which is the case during production build) if (options.extract) { return ExtractTextPlugin.extract({ use: loaders,publicPath: '../../',//解决 build css bg img 加载路径不对问题 fallback: 'react-style-loader' // 修改vue-style-loader }) } else { return ['react-style-loader'].concat(loaders) } } // https://vue-loader.vuejs.org/en/configurations/extract-css.html return { css: generateLoaders(),postcss: generateLoaders(),less: generateLoaders('less'),sass: generateLoaders('sass',{ indentedSyntax: true }),scss: generateLoaders('sass'),stylus: generateLoaders('stylus'),styl: generateLoaders('stylus') } }
webpack.prod.conf 生产环境的修改,打包时,redux,和babel-polyfill 分离打包配置 配合 webpack.base.conf.js中entry修改
new webpack.optimize.CommonsChunkPlugin({ name: ['app','redux','babel'],//单独提取打包 filename: './static/js/[name].js',minChunks: ({resource}) => { resource && /\.js$/.test(resource) && 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: ['app','babel'] }),
webpack.dev.conf.js和webpack.prod.conf.js 有同一个地方修要, 用于在inde.html上写入外部js
new HtmlWebpackPlugin({ title: config.title,filename: 'index.html',template: 'index.ejs',//修改模板类型 为ejs inject: true,js: config.externalsJs_dev // 开发环境是config.externalsJs_prod }),
当然config.externalsJs_dev 配置到了config/index.js 中
// 提取出的文件链接 externalsJs_dev:[ 'https://cdn.bootcss.com/react/16.0.0/umd/react.development.js','https://cdn.bootcss.com/react-dom/16.0.0/umd/react-dom.development.js','https://cdn.bootcss.com/react-router/4.2.0/react-router.js' ],externalsJs_prod: [ 'https://cdn.bootcss.com/react/16.0.0/umd/react.production.min.js','https://cdn.bootcss.com/react-dom/16.0.0/umd/react-dom.production.min.js','https://cdn.bootcss.com/react-router/4.2.0/react-router.min.js' ],title: 'react-redux-demo' //模板标题删除项目 根目录下的index.html 改为index.ejs, 内容如下
<!DOCTYPE html> <html lang="en"> <head> <Meta charset="UTF-8"> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <div id="root"></div> <% for (var i = 0,item; item = htmlWebpackPlugin.options.js[i++];) { %> <script type="text/javascript" src="<%= item %>"></script> <% } %> </body> </html>目录结构如下 包括打包
运行一下npm run build --report=true 看看打包分析, 暂时未集成babel-runtime
是否要集成babel-runtime 需要修改.babelrc 文件中
"plugins": ["transform-runtime"],取消此行的注释, 打包分析如下
{ "name": "wz","version": "1.0.0","description": "","main": "index.js","scripts": { "dev": "node build/dev-server.js","start": "node build/dev-server.js","build": "node build/build.js" },"author": "","license": "ISC","dependencies": { "cross-env": "^5.0.5","expect": "^1.20.1","node-libs-browser": "^2.0.0","node-sass": "^4.5.3","npm": "^5.3.0","react": "^15.6.1","react-addons-test-utils": "^15.1.0","react-dom": "^15.6.1","react-redux": "^5.0.4","redux": "^3.5.2","redux-logger": "^3.0.1","redux-promise": "^0.5.3","redux-thunk": "^2.1.0","shelljs": "^0.7.8","style-loader": "^0.18.2" },"devDependencies": { "autoprefixer": "^7.1.2","babel-core": "^6.10.4","babel-loader": "^7.1.2","babel-plugin-react-transform": "^2.0.2","babel-plugin-transform-runtime": "^6.23.0","babel-polyfill": "^6.9.1","babel-preset-env": "^1.3.2","babel-preset-react": "^6.11.1","babel-preset-stage-0": "^6.5.0","babel-preset-stage-2": "^6.22.0","babel-register": "^6.9.0","bower-webpack-plugin": "^0.1.9","chalk": "^2.0.1","chromedriver": "^2.27.2","compression-webpack-plugin": "^1.0.0","connect-history-api-fallback": "^1.3.0","copy-webpack-plugin": "^4.1.1","core-js": "^2.0.0","cross-spawn": "^5.0.1","css-loader": "^0.28.5","cssnano": "^3.10.0","eventsource-polyfill": "^0.9.6","express": "^4.14.1","extract-text-webpack-plugin": "^3.0.1","file-loader": "^1.1.5","friendly-errors-webpack-plugin": "^1.6.1","html-webpack-plugin": "^2.29.0","http-proxy-middleware": "^0.17.3","less": "^2.7.2","less-loader": "^4.0.3","minimist": "^1.2.0","open": "0.0.5","opn": "^5.1.0","optimize-css-assets-webpack-plugin": "^3.0.0","ora": "^1.3.0","postcss-import": "^10.0.0","postcss-loader": "^2.0.6","precss": "^2.0.0","react-style-loader": "^1.0.1","react-transform-hmr": "^1.0.4","rimraf": "^2.6.0","url-loader": "^0.6.2","webpack": "^3.5.5","webpack-bundle-analyzer": "^2.9.0","webpack-dev-middleware": "^1.6.1","webpack-dev-server": "^2.4.4","webpack-hot-middleware": "^2.11.0","webpack-merge": "^4.1.0" },"engines": { "node": ">= 4.0.0","npm": ">= 3.0.0" } }
以上可能有不准确的或者冗余地方 请酌情参考