UNPKG

7.88 kBJavaScriptView Raw
1'use strict'
2
3const path = require('path')
4const config = require('../config')
5const vueLoaderConfig = require('./loaders/vue-loader.conf')
6const { getEntries, isInstalled } = require('../libs/utils')
7const { getCommonPkgConf } = require('../libs/hybrid')
8const paths = config.paths
9const tsImportPluginFactory = require('ts-import-plugin')
10
11const isProd = process.env.NODE_ENV === 'production'
12const maraConf = require(paths.marauder)
13const shouldUseSourceMap = isProd && !!maraConf.sourceMap
14
15let tsImportLibs = []
16if (maraConf.tsImportLibs) {
17 if (Array.isArray(maraConf.tsImportLibs)) {
18 tsImportLibs = tsImportLibs.concat(maraConf.tsImportLibs)
19 } else {
20 throw Error('marauder.config.js中的tsImportLibs必须是Array类型!')
21 }
22}
23
24module.exports = function(entry, type) {
25 const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin')
26 const { styleLoaders } = require('./loaders/style-loader')
27 const {
28 babelLoader,
29 babelExternalMoudles
30 } = require('./loaders/babel-loader')
31 const isLib = entry == '__LIB__'
32 const ASSETS = isLib ? '' : config.assetsDir
33 const entryGlob = `src/view/${entry}/index.@(ts|js)`
34 const { vueRuntimeOnly } = config.compiler
35 const isHybridMode = config.build.env.raw['jsbridgeBuildType'] === 'app'
36 const isDevOrBuildCmd = type === 'dev' || type === 'build'
37 let entryConf = {}
38 let externals = []
39 let commonPkgPath = ''
40
41 const useCommonPkg =
42 isDevOrBuildCmd &&
43 isHybridMode &&
44 config.compiler.splitSNC &&
45 isInstalled('@mfelibs/hybridcontainer')
46
47 // hybrid SDK 提升,以尽快建立 jsbridge
48 if (useCommonPkg) {
49 const sncConf = getCommonPkgConf(entryGlob)
50
51 // 使用拆分后的 entry 配置
52 entryConf = sncConf.entry
53 commonPkgPath = sncConf.commonPkgPath
54 externals.push(...sncConf.externals)
55 } else {
56 entryConf = getEntries(entryGlob, require.resolve('./polyfills'))
57 }
58
59 const baseConfig = {
60 // dev, build 环境依赖 base.entry,务必提供
61 entry: entryConf,
62 output: {
63 path: paths.dist,
64 // 统一使用 POSIX 风格拼接路径
65 // webpack 将会处理平台差异
66 // 如果使用 path.join 在 Windows 上会出现路径异常
67 filename: path.posix.join(ASSETS, 'js/[name].js'),
68 chunkFilename: path.posix.join(ASSETS, 'js/[name].async.js')
69 },
70 resolve: {
71 // disable symlinks
72 symlinks: false,
73 // js first
74 extensions: [
75 '.js',
76 '.ts',
77 '.jsx',
78 '.tsx',
79 '.sn',
80 '.vue',
81 '.json',
82 '.mjs'
83 ],
84 // https://doc.webpack-china.org/configuration/resolve/#resolve-mainfields
85 // source 为自定义拓展属性,表示源码入口
86 mainFields: ['source', 'browser', 'module', 'main'],
87 modules: ['node_modules'],
88 alias: {
89 // 使用 `~` 作为 src 别名
90 // 使用特殊符号防止与 npm 包冲突
91 // import '~/css/style.css'
92 '~': paths.src,
93 vue$: `vue/dist/vue${vueRuntimeOnly ? '.runtime' : ''}.esm.js`,
94 'babel-runtime': path.dirname(
95 require.resolve('babel-runtime/package.json')
96 ),
97 // Support React Native Web
98 // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
99 'react-native': 'react-native-web'
100 },
101 plugins: [
102 // Prevents users from importing files from outside of src/ (or node_modules/).
103 // This often causes confusion because we only process files within src/ with babel.
104 // To fix this, we prevent you from importing files out of src/ -- if you'd like to,
105 // please link the files into your node_modules/ and let module-resolution kick in.
106 // Make sure your source files are compiled, as they will not be processed in any way.
107 new ModuleScopePlugin(paths.src, [paths.packageJson])
108 ]
109 },
110 resolveLoader: {
111 modules: [paths.ownNodeModules, paths.nodeModules]
112 },
113 module: {
114 // makes missing exports an error instead of warning
115 strictExportPresence: false,
116 rules: [
117 // Disable require.ensure as it's not a standard language feature.
118 // 为了兼容 bundle-loader 暂时不启用
119 // { parser: { requireEnsure: false } },
120 {
121 oneOf: [
122 ...styleLoaders({
123 sourceMap: shouldUseSourceMap,
124 extract: isProd && type !== 'mc',
125 library: isLib
126 }),
127 {
128 test: /\.(bmp|png|jpe?g|gif|svg)(\?.*)?$/,
129 loader: 'url-loader',
130 options: {
131 limit: 10000,
132 name: path.posix.join(ASSETS, 'img/[name].[hash:8].[ext]')
133 }
134 },
135 {
136 test: /\.ejs$/,
137 loader: 'marauder-ejs-loader'
138 },
139 {
140 test: /\.art$/,
141 loader: 'art-template-loader'
142 },
143 {
144 test: /\.(vue|sn)$/,
145 loader: 'vue-loader',
146 options: vueLoaderConfig
147 },
148 {
149 test: /\.mustache$/,
150 loader: 'mustache-loader'
151 },
152 // Process JS with Babel.
153 babelLoader(isProd),
154 {
155 test: /\.tsx?$/,
156 // require.resolve 将会检查模块是否存在
157 // ts-loader 为可选配置,所以这里不使用 require.resolve
158 loader: 'ts-loader',
159 include: babelExternalMoudles,
160 options: {
161 appendTsSuffixTo: [/\.vue$/],
162 transpileOnly: true,
163 getCustomTransformers: () => ({
164 before: [tsImportPluginFactory(tsImportLibs)]
165 }),
166 compilerOptions: {
167 module: 'ESNext'
168 }
169 }
170 },
171 {
172 test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
173 loader: 'file-loader',
174 options: {
175 name: path.posix.join(ASSETS, 'fonts/[name].[hash:8].[ext]')
176 }
177 },
178 {
179 // Exclude `js` files to keep "css" loader working as it injects
180 // it's runtime that would otherwise processed through "file" loader.
181 // Also exclude `html` and `json` extensions so they get processed
182 // by webpacks internal loaders.
183 loader: 'file-loader',
184 exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
185 options: {
186 name: path.posix.join(ASSETS, 'media/[name].[hash:8].[ext]')
187 }
188 },
189 {
190 test: /\.(html)$/,
191 use: {
192 loader: 'html-loader',
193 options: {
194 attrs: [':src', ':data-src']
195 }
196 }
197 },
198 {
199 test: /\.txt$/,
200 loader: 'raw-loader'
201 }
202 ]
203 }
204 ]
205 },
206 plugins: [],
207 externals: externals,
208 // Some libraries import Node modules but don't use them in the browser.
209 // Tell Webpack to provide empty mocks for them so importing them works.
210 node: {
211 // prevent webpack from injecting useless setImmediate polyfill because Vue
212 // source contains it (although only uses it if it's native).
213 setImmediate: false,
214 dgram: 'empty',
215 fs: 'empty',
216 net: 'empty',
217 tls: 'empty',
218 child_process: 'empty'
219 }
220 }
221
222 if (isDevOrBuildCmd && isHybridMode) {
223 const { SinaHybridPlugin } = require('../libs/hybrid')
224
225 // 确保在 copy Files 之前
226 baseConfig.plugins.push(
227 new SinaHybridPlugin({
228 entry: entry,
229 commonPkgPath: commonPkgPath,
230 useCommonPkg: useCommonPkg
231 })
232 )
233 }
234
235 return baseConfig
236}