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 { splitSNC } = 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 |
|
40 | const shouldSNCHoisting =
|
41 | isDevOrBuildCmd &&
|
42 | isHybridMode &&
|
43 | config.compiler.splitSNC &&
|
44 | isInstalled('@mfelibs/universal-framework')
|
45 |
|
46 |
|
47 | if (shouldSNCHoisting) {
|
48 | const sncConf = splitSNC(entryGlob)
|
49 |
|
50 |
|
51 | entryConf = sncConf.entry
|
52 | externals.push(...sncConf.externals)
|
53 | } else {
|
54 | entryConf = getEntries(entryGlob, require.resolve('./polyfills'))
|
55 | }
|
56 |
|
57 | const baseConfig = {
|
58 |
|
59 | entry: entryConf,
|
60 | output: {
|
61 | path: paths.dist,
|
62 |
|
63 |
|
64 |
|
65 | filename: path.posix.join(ASSETS, 'js/[name].js'),
|
66 | chunkFilename: path.posix.join(ASSETS, 'js/[name].async.js')
|
67 | },
|
68 | resolve: {
|
69 |
|
70 | symlinks: false,
|
71 |
|
72 | extensions: [
|
73 | '.js',
|
74 | '.ts',
|
75 | '.jsx',
|
76 | '.tsx',
|
77 | '.sn',
|
78 | '.vue',
|
79 | '.json',
|
80 | '.mjs'
|
81 | ],
|
82 |
|
83 |
|
84 | mainFields: ['source', 'browser', 'module', 'main'],
|
85 | modules: ['node_modules'],
|
86 | alias: {
|
87 |
|
88 |
|
89 |
|
90 | '~': paths.src,
|
91 | vue$: `vue/dist/vue${vueRuntimeOnly ? '.runtime' : ''}.esm.js`,
|
92 | 'babel-runtime': path.dirname(
|
93 | require.resolve('babel-runtime/package.json')
|
94 | ),
|
95 |
|
96 |
|
97 | 'react-native': 'react-native-web'
|
98 | },
|
99 | plugins: [
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 | new ModuleScopePlugin(paths.src, [paths.packageJson])
|
106 | ]
|
107 | },
|
108 | resolveLoader: {
|
109 | modules: [paths.ownNodeModules, paths.nodeModules]
|
110 | },
|
111 | module: {
|
112 |
|
113 | strictExportPresence: false,
|
114 | rules: [
|
115 |
|
116 |
|
117 |
|
118 | {
|
119 | oneOf: [
|
120 | ...styleLoaders({
|
121 | sourceMap: shouldUseSourceMap,
|
122 | extract: isProd && type !== 'mc',
|
123 | library: isLib
|
124 | }),
|
125 | {
|
126 | test: /\.(bmp|png|jpe?g|gif|svg)(\?.*)?$/,
|
127 | loader: 'url-loader',
|
128 | options: {
|
129 | limit: 10000,
|
130 | name: path.posix.join(ASSETS, 'img/[name].[hash:8].[ext]')
|
131 | }
|
132 | },
|
133 | {
|
134 | test: /\.ejs$/,
|
135 | loader: 'marauder-ejs-loader'
|
136 | },
|
137 | {
|
138 | test: /\.art$/,
|
139 | loader: 'art-template-loader'
|
140 | },
|
141 | {
|
142 | test: /\.(vue|sn)$/,
|
143 | loader: 'vue-loader',
|
144 | options: vueLoaderConfig
|
145 | },
|
146 | {
|
147 | test: /\.mustache$/,
|
148 | loader: 'mustache-loader'
|
149 | },
|
150 |
|
151 | babelLoader(isProd),
|
152 | {
|
153 | test: /\.tsx?$/,
|
154 |
|
155 |
|
156 | loader: 'ts-loader',
|
157 | include: babelExternalMoudles,
|
158 | options: {
|
159 | appendTsSuffixTo: [/\.vue$/],
|
160 | transpileOnly: true,
|
161 | getCustomTransformers: () => ({
|
162 | before: [tsImportPluginFactory(tsImportLibs)]
|
163 | }),
|
164 | compilerOptions: {
|
165 | module: 'ESNext'
|
166 | }
|
167 | }
|
168 | },
|
169 | {
|
170 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
|
171 | loader: 'file-loader',
|
172 | options: {
|
173 | name: path.posix.join(ASSETS, 'fonts/[name].[hash:8].[ext]')
|
174 | }
|
175 | },
|
176 | {
|
177 |
|
178 |
|
179 |
|
180 |
|
181 | loader: 'file-loader',
|
182 | exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
|
183 | options: {
|
184 | name: path.posix.join(ASSETS, 'media/[name].[hash:8].[ext]')
|
185 | }
|
186 | },
|
187 | {
|
188 | test: /\.(html)$/,
|
189 | use: {
|
190 | loader: 'html-loader',
|
191 | options: {
|
192 | attrs: [':src', ':data-src']
|
193 | }
|
194 | }
|
195 | }
|
196 | ]
|
197 | }
|
198 | ]
|
199 | },
|
200 | plugins: [],
|
201 | externals: externals,
|
202 |
|
203 |
|
204 | node: {
|
205 |
|
206 |
|
207 | setImmediate: false,
|
208 | dgram: 'empty',
|
209 | fs: 'empty',
|
210 | net: 'empty',
|
211 | tls: 'empty',
|
212 | child_process: 'empty'
|
213 | }
|
214 | }
|
215 |
|
216 | if (isHybridMode) {
|
217 | const { SinaHybridPlugin } = require('../libs/hybrid')
|
218 |
|
219 |
|
220 | baseConfig.plugins.push(
|
221 | new SinaHybridPlugin({
|
222 | entry: entry,
|
223 | splitSNC: shouldSNCHoisting
|
224 | })
|
225 | )
|
226 | }
|
227 |
|
228 | return baseConfig
|
229 | }
|