1 | 'use strict'
|
2 |
|
3 | const path = require('path')
|
4 | const config = require('../config')
|
5 | const vueLoaderConfig = require('./loaders/vue-loader.conf')
|
6 | const { getEntries, isInstalled } = require('../libs/utils')
|
7 | const { getCommonPkgConf } = require('../libs/hybrid')
|
8 | const paths = config.paths
|
9 | const tsImportPluginFactory = require('ts-import-plugin')
|
10 |
|
11 | const isProd = process.env.NODE_ENV === 'production'
|
12 | const maraConf = require(paths.marauder)
|
13 | const shouldUseSourceMap = isProd && !!maraConf.sourceMap
|
14 |
|
15 | let tsImportLibs = []
|
16 | if (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 |
|
24 | module.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 |
|
48 | if (useCommonPkg) {
|
49 | const sncConf = getCommonPkgConf(entryGlob)
|
50 |
|
51 |
|
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 |
|
61 | entry: entryConf,
|
62 | output: {
|
63 | path: paths.dist,
|
64 |
|
65 |
|
66 |
|
67 | filename: path.posix.join(ASSETS, 'js/[name].js'),
|
68 | chunkFilename: path.posix.join(ASSETS, 'js/[name].async.js')
|
69 | },
|
70 | resolve: {
|
71 |
|
72 | symlinks: false,
|
73 |
|
74 | extensions: [
|
75 | '.js',
|
76 | '.ts',
|
77 | '.jsx',
|
78 | '.tsx',
|
79 | '.sn',
|
80 | '.vue',
|
81 | '.json',
|
82 | '.mjs'
|
83 | ],
|
84 |
|
85 |
|
86 | mainFields: ['source', 'browser', 'module', 'main'],
|
87 | modules: ['node_modules'],
|
88 | alias: {
|
89 |
|
90 |
|
91 |
|
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 |
|
98 |
|
99 | 'react-native': 'react-native-web'
|
100 | },
|
101 | plugins: [
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 | new ModuleScopePlugin(paths.src, [paths.packageJson])
|
108 | ]
|
109 | },
|
110 | resolveLoader: {
|
111 | modules: [paths.ownNodeModules, paths.nodeModules]
|
112 | },
|
113 | module: {
|
114 |
|
115 | strictExportPresence: false,
|
116 | rules: [
|
117 |
|
118 |
|
119 |
|
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 |
|
153 | babelLoader(isProd),
|
154 | {
|
155 | test: /\.tsx?$/,
|
156 |
|
157 |
|
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 |
|
180 |
|
181 |
|
182 |
|
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 |
|
209 |
|
210 | node: {
|
211 |
|
212 |
|
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 |
|
226 | baseConfig.plugins.push(
|
227 | new SinaHybridPlugin({
|
228 | entry: entry,
|
229 | commonPkgPath: commonPkgPath,
|
230 | useCommonPkg: useCommonPkg
|
231 | })
|
232 | )
|
233 | }
|
234 |
|
235 | return baseConfig
|
236 | }
|