UNPKG

6.87 kBJavaScriptView Raw
1'use strict'
2
3const path = require('path')
4const webpack = require('webpack')
5const merge = require('webpack-merge')
6const HtmlWebpackPlugin = require('sina-html-webpack-plugin')
7const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin')
8const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin')
9const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
10const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
11const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware')
12const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware')
13const DuplicatePackageCheckerPlugin = require('duplicate-package-checker-webpack-plugin')
14const ignoredFiles = require('react-dev-utils/ignoredFiles')
15const { localIp, getChunks, rootPath } = require('../libs/utils')
16const config = require('../config')
17
18function parseChunks(entry) {
19 const chunkObj = getChunks(`src/view/${entry}/index.*.js`)
20 const chunks = [].concat(...Object.values(chunkObj))
21
22 return { [entry]: chunks }
23}
24
25module.exports = function({ entry }) {
26 const baseWebpackConfig = require('./webpack.base.conf')(entry, 'dev')
27 const pagePublicDir = rootPath(`${config.paths.page}/${entry}/public`)
28 const chunksEntry = parseChunks(entry)
29 const { transformer, formatter } = require('../libs/resolveLoaderError')
30
31 // https://github.com/survivejs/webpack-merge
32 // 当 entry 为数组时,webpack-merge 默认执行 append
33 const webpackConfig = merge(baseWebpackConfig, {
34 devtool: 'cheap-module-source-map',
35 entry: chunksEntry,
36 output: {
37 publicPath: config.dev.assetsPublicPath,
38 // Point sourcemap entries to original disk location (format as URL on Windows)
39 devtoolModuleFilenameTemplate: info =>
40 path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'),
41 // Add /* filename */ comments to generated require()s in the output.
42 pathinfo: true
43 },
44 devServer: {
45 // 允许修改 host 模拟跨域
46 disableHostCheck: true,
47 headers: { 'Access-Control-Allow-Origin': '*' },
48 // 开启 gzip 压缩
49 compress: true,
50 // 屏蔽 WebpackDevServer 自身的日志输出
51 // 此设置不影响警告与错误信息
52 clientLogLevel: 'none',
53 // 注意,不要通过 webpack import public 内的资源
54 // 对于脚本及样式,应使用 script,link 标签引入
55 // <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
56 // 在 js 内,可使用 process.env.PUBLIC 获取路径
57 contentBase: [
58 config.paths.public,
59 pagePublicDir
60 // @FIXME 监听 html 文件变化,临时措施
61 // `${config.paths.page}/${entry}/*.html`
62 ],
63 // 监听 public 文件夹内容变化
64 watchContentBase: true,
65 // 开启服务器热更新. 它将为 WebpackDevServer 客户端注入 /sockjs-node/ 节点
66 // 从而能够感知文件何时被更新。WebpackDevServer 客户端将会被添加到 Webpack 开发配置
67 // 的入口中。 注意,目前只有 css 能够热更新,js 的改动依然会触发浏览器刷新
68 hot: true,
69 // 指定资源根路径.
70 publicPath: config.dev.assetsPublicPath,
71 // WebpackDevServer 的默认输出会有很多干扰项,所以我们使用自定义信息代替
72 quiet: true,
73 // 据说这么做在某些系统上能避免 CPU 过载。
74 // https://github.com/facebookincubator/create-react-app/issues/293
75 // src/node_modules 不被忽略以支持使用绝对路径导入
76 // https://github.com/facebook/create-react-app/issues/1065
77 watchOptions: {
78 ignored: ignoredFiles(config.paths.src)
79 },
80 host: localIp(),
81 overlay: false,
82 historyApiFallback: {
83 // Paths with dots should still use the history fallback.
84 // See https://github.com/facebook/create-react-app/issues/387.
85 disableDotRule: true
86 },
87 // public: allowedHost,
88 // proxy,
89 before(app) {
90 // This lets us open files from the runtime error overlay.
91 app.use(errorOverlayMiddleware())
92 // This service worker file is effectively a 'no-op' that will reset any
93 // previous service worker registered for the same host:port combination.
94 // We do this in development to avoid hitting the production cache if
95 // it used the same host and port.
96 // https://github.com/facebookincubator/create-react-app/issues/2272#issuecomment-302832432
97 app.use(noopServiceWorkerMiddleware())
98 }
99 },
100 plugins: [
101 new webpack.DefinePlugin(config.dev.env.stringified),
102 // 替换 html 内的环境变量
103 // %PUBLIC% 转换为具体路径
104 // 在 dev 环境下为空字符串
105 new InterpolateHtmlPlugin(config.dev.env.raw),
106 new webpack.NamedModulesPlugin(),
107 new DuplicatePackageCheckerPlugin({
108 // show details
109 verbose: true,
110 showHelp: false,
111 // show warning
112 emitError: false,
113 // check major version
114 strict: true
115 }),
116 // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
117 new webpack.HotModuleReplacementPlugin(),
118 // 出错时只打印错误,但不重新加载页面
119 new webpack.NoEmitOnErrorsPlugin(),
120 // 安装缺失模块后不用重启服务
121 new WatchMissingNodeModulesPlugin(config.paths.nodeModules),
122 // friendly error plugin displays very confusing errors when webpack
123 // fails to resolve a loader, so we provide custom handlers to improve it
124 new FriendlyErrorsPlugin({
125 additionalTransformers: [transformer],
126 additionalFormatters: [formatter]
127 }),
128 new CaseSensitivePathsPlugin(),
129 // Moment.js is an extremely popular library that bundles large locale files
130 // by default due to how Webpack interprets its code. This is a practical
131 // solution that requires the user to opt into importing specific locales.
132 // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
133 // You can remove this if you don't use Moment.js:
134 new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
135 new HtmlWebpackPlugin({
136 // 以页面文件夹名作为模板名称
137 filename: `${entry}.html`,
138 // 生成各自的 html 模板
139 template: `${config.paths.page}/${entry}/index.html`,
140 inject: true,
141 // 每个html引用的js模块,也可以在这里加上vendor等公用模块
142 chunks: [entry]
143 })
144 ],
145 // Turn off performance hints during development because we don't do any
146 // splitting or minification in interest of speed. These warnings become
147 // cumbersome.
148 performance: {
149 hints: false
150 }
151 })
152
153 return webpackConfig
154}